print: Move all the remaining sources
authorMatthias Clasen <mclasen@redhat.com>
Wed, 7 Jun 2023 03:14:39 +0000 (23:14 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Wed, 7 Jun 2023 04:06:33 +0000 (00:06 -0400)
Move the unix- and Windows-specific print
sources to the gtk/print subdirectory.

68 files changed:
gtk/gtkcustompaperunixdialog.c [deleted file]
gtk/gtkcustompaperunixdialog.h [deleted file]
gtk/gtkmain.c
gtk/gtkpagesetupunixdialog.c [deleted file]
gtk/gtkpagesetupunixdialog.h [deleted file]
gtk/gtkprint-win32.c [deleted file]
gtk/gtkprint-win32.h [deleted file]
gtk/gtkprintbackend.c [deleted file]
gtk/gtkprintbackendprivate.h [deleted file]
gtk/gtkprinter.c [deleted file]
gtk/gtkprinter.h [deleted file]
gtk/gtkprinteroption.c [deleted file]
gtk/gtkprinteroptionprivate.h [deleted file]
gtk/gtkprinteroptionset.c [deleted file]
gtk/gtkprinteroptionsetprivate.h [deleted file]
gtk/gtkprinteroptionwidget.c [deleted file]
gtk/gtkprinteroptionwidgetprivate.h [deleted file]
gtk/gtkprinterprivate.h [deleted file]
gtk/gtkprintjob.c [deleted file]
gtk/gtkprintjob.h [deleted file]
gtk/gtkprintoperation-portal.c [deleted file]
gtk/gtkprintoperation-portal.h [deleted file]
gtk/gtkprintoperation-private.h [deleted file]
gtk/gtkprintoperation-unix.c [deleted file]
gtk/gtkprintoperation-win32.c [deleted file]
gtk/gtkprintunixdialog.c [deleted file]
gtk/gtkprintunixdialog.h [deleted file]
gtk/gtkprintutilsprivate.h [deleted file]
gtk/gtkunixprint.h [deleted file]
gtk/meson.build
gtk/paper_names.c [deleted file]
gtk/paper_names_offsets.c [deleted file]
gtk/print/gtkcustompaperunixdialog.c [new file with mode: 0644]
gtk/print/gtkcustompaperunixdialog.h [new file with mode: 0644]
gtk/print/gtkpagesetupunixdialog.c [new file with mode: 0644]
gtk/print/gtkpagesetupunixdialog.h [new file with mode: 0644]
gtk/print/gtkprint-win32.c [new file with mode: 0644]
gtk/print/gtkprint-win32.h [new file with mode: 0644]
gtk/print/gtkprintbackend.c [new file with mode: 0644]
gtk/print/gtkprintbackendprivate.h [new file with mode: 0644]
gtk/print/gtkprinter.c [new file with mode: 0644]
gtk/print/gtkprinter.h [new file with mode: 0644]
gtk/print/gtkprinteroption.c [new file with mode: 0644]
gtk/print/gtkprinteroptionprivate.h [new file with mode: 0644]
gtk/print/gtkprinteroptionset.c [new file with mode: 0644]
gtk/print/gtkprinteroptionsetprivate.h [new file with mode: 0644]
gtk/print/gtkprinteroptionwidget.c [new file with mode: 0644]
gtk/print/gtkprinteroptionwidgetprivate.h [new file with mode: 0644]
gtk/print/gtkprinterprivate.h [new file with mode: 0644]
gtk/print/gtkprintjob.c [new file with mode: 0644]
gtk/print/gtkprintjob.h [new file with mode: 0644]
gtk/print/gtkprintoperation-portal.c [new file with mode: 0644]
gtk/print/gtkprintoperation-portal.h [new file with mode: 0644]
gtk/print/gtkprintoperation-private.h [new file with mode: 0644]
gtk/print/gtkprintoperation-unix.c [new file with mode: 0644]
gtk/print/gtkprintoperation-win32.c [new file with mode: 0644]
gtk/print/gtkprintunixdialog.c [new file with mode: 0644]
gtk/print/gtkprintunixdialog.h [new file with mode: 0644]
gtk/print/gtkprintutilsprivate.h [new file with mode: 0644]
gtk/print/gtkunixprint.h [new file with mode: 0644]
gtk/print/meson.build
gtk/print/paper_names.c [new file with mode: 0644]
gtk/print/paper_names_offsets.c [new file with mode: 0644]
modules/printbackends/gtkprintbackendcups.c
modules/printbackends/gtkprintbackendcups.h
modules/printbackends/gtkprintbackendfile.c
modules/printbackends/gtkprintbackendfile.h
modules/printbackends/gtkprintercups.h

diff --git a/gtk/gtkcustompaperunixdialog.c b/gtk/gtkcustompaperunixdialog.c
deleted file mode 100644 (file)
index 375927e..0000000
+++ /dev/null
@@ -1,1008 +0,0 @@
-/* GtkCustomPaperUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007, 2008 Christian Persch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "config.h"
-#include <string.h>
-#include <locale.h>
-
-#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
-#include <langinfo.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-
-#include "deprecated/gtkliststore.h"
-
-#include "gtksignallistitemfactory.h"
-#include "gtklabel.h"
-#include "gtkspinbutton.h"
-
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprintutilsprivate.h"
-#include "deprecated/gtkdialogprivate.h"
-
-#define LEGACY_CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
-#define CUSTOM_PAPER_FILENAME "custom-papers"
-
-
-typedef struct
-{
-  GtkUnit    display_unit;
-  GtkWidget *spin_button;
-} UnitWidget;
-
-struct _GtkCustomPaperUnixDialog
-{
-  GtkDialog parent_instance;
-
-  GtkWidget *listview;
-  GtkWidget *values_box;
-  GtkWidget *printer_combo;
-  GtkWidget *width_widget;
-  GtkWidget *height_widget;
-  GtkWidget *top_widget;
-  GtkWidget *bottom_widget;
-  GtkWidget *left_widget;
-  GtkWidget *right_widget;
-
-  gulong printer_inserted_tag;
-
-  guint request_details_tag;
-  GtkPrinter *request_details_printer;
-
-  guint non_user_change : 1;
-
-  GListStore *custom_paper_list;
-  GListModel *printer_list;
-
-  GList *print_backends;
-};
-
-typedef struct _GtkCustomPaperUnixDialogClass GtkCustomPaperUnixDialogClass;
-
-struct _GtkCustomPaperUnixDialogClass
-{
-  GtkDialogClass parent_class;
-};
-
-
-enum {
-  PRINTER_LIST_COL_NAME,
-  PRINTER_LIST_COL_PRINTER,
-  PRINTER_LIST_N_COLS
-};
-
-
-G_DEFINE_TYPE (GtkCustomPaperUnixDialog, gtk_custom_paper_unix_dialog, GTK_TYPE_DIALOG)
-
-
-static void gtk_custom_paper_unix_dialog_constructed (GObject *object);
-static void gtk_custom_paper_unix_dialog_finalize  (GObject                *object);
-static void populate_dialog                        (GtkCustomPaperUnixDialog *dialog);
-
-
-
-GtkUnit
-_gtk_print_get_default_user_units (void)
-{
-  /* Translate to the default units to use for presenting
-   * lengths to the user. Translate to default:inch if you
-   * want inches, otherwise translate to default:mm.
-   * Do *not* translate it to "predefinito:mm", if it
-   * it isn't default:mm or default:inch it will not work
-   */
-  char *e = _("default:mm");
-
-#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
-  char *imperial = NULL;
-
-  imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
-  if (imperial && imperial[0] == 2 )
-    return GTK_UNIT_INCH;  /* imperial */
-  if (imperial && imperial[0] == 1 )
-    return GTK_UNIT_MM;  /* metric */
-#endif
-
-  if (strcmp (e, "default:inch")==0)
-    return GTK_UNIT_INCH;
-  else if (strcmp (e, "default:mm"))
-    g_warning ("Whoever translated default:mm did so wrongly.");
-  return GTK_UNIT_MM;
-}
-
-static char *
-custom_paper_get_legacy_filename (void)
-{
-  char *filename;
-
-  filename = g_build_filename (g_get_home_dir (),
-                               LEGACY_CUSTOM_PAPER_FILENAME, NULL);
-  g_assert (filename != NULL);
-  return filename;
-}
-
-static char *
-custom_paper_get_filename (void)
-{
-  char *filename;
-
-  filename = g_build_filename (g_get_user_config_dir (),
-                               "gtk-4.0",
-                               CUSTOM_PAPER_FILENAME, NULL);
-  g_assert (filename != NULL);
-  return filename;
-}
-
-GList *
-_gtk_load_custom_papers (void)
-{
-  GKeyFile *keyfile;
-  char *filename;
-  char **groups;
-  gsize n_groups, i;
-  gboolean load_ok;
-  GList *result = NULL;
-
-  filename = custom_paper_get_filename ();
-
-  keyfile = g_key_file_new ();
-  load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
-  g_free (filename);
-  if (!load_ok)
-    {
-      /* try legacy file */
-      filename = custom_paper_get_legacy_filename ();
-      load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
-      g_free (filename);
-    }
-  if (!load_ok)
-    {
-      g_key_file_free (keyfile);
-      return NULL;
-    }
-
-  groups = g_key_file_get_groups (keyfile, &n_groups);
-  for (i = 0; i < n_groups; ++i)
-    {
-      GtkPageSetup *page_setup;
-
-      page_setup = gtk_page_setup_new_from_key_file (keyfile, groups[i], NULL);
-      if (!page_setup)
-        continue;
-
-      result = g_list_prepend (result, page_setup);
-    }
-
-  g_strfreev (groups);
-  g_key_file_free (keyfile);
-
-  return g_list_reverse (result);
-}
-
-void
-gtk_print_load_custom_papers (GListStore *store)
-{
-  GList *papers, *p;
-  GtkPageSetup *page_setup;
-
-  g_list_store_remove_all (store);
-
-  papers = _gtk_load_custom_papers ();
-  for (p = papers; p; p = p->next)
-    {
-      page_setup = p->data;
-      g_list_store_append (store, page_setup);
-      g_object_unref (page_setup);
-    }
-
-  g_list_free (papers);
-}
-
-static void
-gtk_print_save_custom_papers (GListStore *store)
-{
-  GKeyFile *keyfile;
-  char *filename, *data, *parentdir;
-  gsize len;
-  int i = 0;
-
-  keyfile = g_key_file_new ();
-
-  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
-    {
-      GtkPageSetup *page_setup;
-      char group[32];
-
-      page_setup = g_list_model_get_item (G_LIST_MODEL (store), i);
-      g_snprintf (group, sizeof (group), "Paper%u", i);
-      gtk_page_setup_to_key_file (page_setup, keyfile, group);
-      g_object_unref (page_setup);
-    }
-
-  filename = custom_paper_get_filename ();
-  parentdir = g_build_filename (g_get_user_config_dir (),
-                                "gtk-4.0",
-                                NULL);
-  if (g_mkdir_with_parents (parentdir, 0700) == 0)
-    {
-      data = g_key_file_to_data (keyfile, &len, NULL);
-      g_file_set_contents (filename, data, len, NULL);
-      g_free (data);
-    }
-  g_free (parentdir);
-  g_free (filename);
-}
-
-static void
-gtk_custom_paper_unix_dialog_class_init (GtkCustomPaperUnixDialogClass *class)
-{
-  G_OBJECT_CLASS (class)->constructed = gtk_custom_paper_unix_dialog_constructed;
-  G_OBJECT_CLASS (class)->finalize = gtk_custom_paper_unix_dialog_finalize;
-}
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *dialog,
-                                 int        response,
-                                 gpointer   user_data)
-{
-  GtkCustomPaperUnixDialog *self = GTK_CUSTOM_PAPER_UNIX_DIALOG (dialog);
-
-  gtk_print_save_custom_papers (self->custom_paper_list);
-}
-
-static gboolean
-match_func (gpointer item, gpointer user_data)
-{
-  return !gtk_printer_is_virtual (GTK_PRINTER (item));
-}
-
-static void
-gtk_custom_paper_unix_dialog_init (GtkCustomPaperUnixDialog *dialog)
-{
-  GtkPrinter *printer;
-  GListStore *printer_list;
-  GListStore *printer_list_list;
-  GListModel *full_list;
-  GtkFilter *filter;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-  dialog->print_backends = NULL;
-
-  dialog->request_details_printer = NULL;
-  dialog->request_details_tag = 0;
-
-  printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
-  printer_list = g_list_store_new (GTK_TYPE_PRINTER);
-  printer = gtk_printer_new (_("Margins from Printer…"), NULL, FALSE);
-  g_list_store_append (printer_list, printer);
-  g_object_unref (printer);
-  g_list_store_append (printer_list_list, printer_list);
-  g_object_unref (printer_list);
-
-  full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
-
-  filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
-  dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
-
-  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-
-  populate_dialog (dialog);
-
-  g_signal_connect (dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), NULL);
-}
-
-static void
-gtk_custom_paper_unix_dialog_constructed (GObject *object)
-{
-  gboolean use_header;
-
-  G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->constructed (object);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  g_object_get (object, "use-header-bar", &use_header, NULL);
-  if (!use_header)
-    {
-      gtk_dialog_add_buttons (GTK_DIALOG (object),
-                              _("_Close"), GTK_RESPONSE_CLOSE,
-                              NULL);
-      gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_CLOSE);
-    }
-G_GNUC_END_IGNORE_DEPRECATIONS
-}
-
-static void
-gtk_custom_paper_unix_dialog_finalize (GObject *object)
-{
-  GtkCustomPaperUnixDialog *dialog = GTK_CUSTOM_PAPER_UNIX_DIALOG (object);
-  GList *node;
-
-  if (dialog->printer_list)
-    {
-      g_signal_handler_disconnect (dialog->printer_list, dialog->printer_inserted_tag);
-      g_object_unref (dialog->printer_list);
-      dialog->printer_list = NULL;
-    }
-
-  if (dialog->request_details_tag)
-    {
-      g_signal_handler_disconnect (dialog->request_details_printer,
-                                   dialog->request_details_tag);
-      g_object_unref (dialog->request_details_printer);
-      dialog->request_details_printer = NULL;
-      dialog->request_details_tag = 0;
-    }
-
-  g_clear_object (&dialog->custom_paper_list);
-
-  for (node = dialog->print_backends; node; node = node->next)
-    gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
-  g_list_free_full (dialog->print_backends, g_object_unref);
-  dialog->print_backends = NULL;
-
-  G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->finalize (object);
-}
-
-/**
- * gtk_custom_paper_unix_dialog_new:
- * @title: (nullable): the title of the dialog
- * @parent: (nullable): transient parent of the dialog
- *
- * Creates a new custom paper dialog.
- *
- * Returns: the new `GtkCustomPaperUnixDialog`
- */
-GtkWidget *
-_gtk_custom_paper_unix_dialog_new (GtkWindow   *parent,
-                                   const char *title)
-{
-  GtkWidget *result;
-
-  if (title == NULL)
-    title = _("Manage Custom Sizes");
-
-  result = g_object_new (GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG,
-                         "title", title,
-                         "transient-for", parent,
-                         "modal", parent != NULL,
-                         "destroy-with-parent", TRUE,
-                         "resizable", FALSE,
-                         NULL);
-
-  return result;
-}
-
-static void
-load_print_backends (GtkCustomPaperUnixDialog *dialog)
-{
-  GListModel *full_list;
-  GListStore *printer_list_list;
-  GList *node;
-
-  full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
-  printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
-
-  if (g_module_supported ())
-    dialog->print_backends = gtk_print_backend_load_modules ();
-
-  for (node = dialog->print_backends; node != NULL; node = node->next)
-    {
-      GtkPrintBackend *backend = GTK_PRINT_BACKEND (node->data);
-      g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
-    }
-}
-
-static void unit_widget_changed (GtkCustomPaperUnixDialog *dialog);
-
-static GtkWidget *
-new_unit_widget (GtkCustomPaperUnixDialog *dialog,
-                 GtkUnit                   unit,
-                 GtkWidget                *mnemonic_label)
-{
-  GtkWidget *hbox, *button, *label;
-  UnitWidget *data;
-
-  data = g_new0 (UnitWidget, 1);
-  data->display_unit = unit;
-
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-
-  button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
-  gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
-  if (unit == GTK_UNIT_INCH)
-    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
-  else
-    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
-
-  gtk_box_append (GTK_BOX (hbox), button);
-
-  data->spin_button = button;
-
-  g_signal_connect_swapped (button, "value-changed",
-                            G_CALLBACK (unit_widget_changed), dialog);
-
-  if (unit == GTK_UNIT_INCH)
-    label = gtk_label_new (_("inch"));
-  else
-    label = gtk_label_new (_("mm"));
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-
-  gtk_box_append (GTK_BOX (hbox), label);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (mnemonic_label), button);
-
-  g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
-
-  return hbox;
-}
-
-static double
-unit_widget_get (GtkWidget *unit_widget)
-{
-  UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
-  return _gtk_print_convert_to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
-                                   data->display_unit);
-}
-
-static void
-unit_widget_set (GtkWidget *unit_widget,
-                 double     value)
-{
-  UnitWidget *data;
-
-  data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
-                             _gtk_print_convert_from_mm (value, data->display_unit));
-}
-
-static void
-update_combo_sensitivity_from_printers (GtkCustomPaperUnixDialog *dialog)
-{
-  gboolean sensitive = FALSE;
-
-  if (g_list_model_get_n_items (dialog->printer_list) > 1)
-    sensitive = TRUE;
-
-  gtk_widget_set_sensitive (dialog->printer_combo, sensitive);
-}
-
-static void
-update_custom_widgets_from_list (GtkCustomPaperUnixDialog *dialog)
-{
-  GListModel *model;
-  GtkPageSetup *page_setup;
-
-  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
-  page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
-  dialog->non_user_change = TRUE;
-  if (page_setup != NULL)
-    {
-      unit_widget_set (dialog->width_widget,
-                       gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
-      unit_widget_set (dialog->height_widget,
-                       gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
-      unit_widget_set (dialog->top_widget,
-                       gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
-      unit_widget_set (dialog->bottom_widget,
-                       gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
-      unit_widget_set (dialog->left_widget,
-                       gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
-      unit_widget_set (dialog->right_widget,
-                       gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
-
-      gtk_widget_set_sensitive (dialog->values_box, TRUE);
-    }
-  else
-    {
-      gtk_widget_set_sensitive (dialog->values_box, FALSE);
-    }
-
-  if (dialog->printer_list)
-    update_combo_sensitivity_from_printers (dialog);
-  dialog->non_user_change = FALSE;
-}
-
-static void
-selected_custom_paper_changed (GObject                  *list,
-                               GParamSpec               *pspec,
-                               GtkCustomPaperUnixDialog *dialog)
-{
-  update_custom_widgets_from_list (dialog);
-}
-
-static void
-unit_widget_changed (GtkCustomPaperUnixDialog *dialog)
-{
-  double w, h, top, bottom, left, right;
-  GListModel *model;
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-
-  if (dialog->non_user_change)
-    return;
-
-  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
-  page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
-  if (page_setup != NULL)
-    {
-      w = unit_widget_get (dialog->width_widget);
-      h = unit_widget_get (dialog->height_widget);
-
-      paper_size = gtk_page_setup_get_paper_size (page_setup);
-      gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
-
-      top = unit_widget_get (dialog->top_widget);
-      bottom = unit_widget_get (dialog->bottom_widget);
-      left = unit_widget_get (dialog->left_widget);
-      right = unit_widget_get (dialog->right_widget);
-
-      gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
-      gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
-      gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
-      gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
-    }
-}
-
-static gboolean
-custom_paper_name_used (GtkCustomPaperUnixDialog *dialog,
-                        const char               *name)
-{
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-  guint i;
-
-  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)); i++)
-    {
-      page_setup = g_list_model_get_item (G_LIST_MODEL (dialog->custom_paper_list), i);
-      paper_size = gtk_page_setup_get_paper_size (page_setup);
-      if (strcmp (name, gtk_paper_size_get_name (paper_size)) == 0)
-        {
-          g_object_unref (page_setup);
-          return TRUE;
-        }
-      g_object_unref (page_setup);
-    }
-
-  return FALSE;
-}
-
-static void
-add_custom_paper (GtkCustomPaperUnixDialog *dialog)
-{
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-  char *name;
-  int i;
-
-  i = 1;
-  name = NULL;
-  do
-    {
-      g_free (name);
-      name = g_strdup_printf (_("Custom Size %d"), i);
-      i++;
-    } while (custom_paper_name_used (dialog, name));
-
-  page_setup = gtk_page_setup_new ();
-  paper_size = gtk_paper_size_new_custom (name, name,
-                                          gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
-                                          gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
-                                          GTK_UNIT_MM);
-  gtk_page_setup_set_paper_size (page_setup, paper_size);
-  gtk_paper_size_free (paper_size);
-
-  g_list_store_append (dialog->custom_paper_list, page_setup);
-  g_object_unref (page_setup);
-
-  /* FIXME start editing */
-
-  g_free (name);
-}
-
-static void
-remove_custom_paper (GtkCustomPaperUnixDialog *dialog)
-{
-  GListModel *model;
-  guint selected;
-
-  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
-  selected = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model));
-  if (selected != GTK_INVALID_LIST_POSITION)
-    g_list_store_remove (dialog->custom_paper_list, selected);
-}
-
-static void
-set_margins_from_printer (GtkCustomPaperUnixDialog *dialog,
-                          GtkPrinter               *printer)
-{
-  double top, bottom, left, right;
-
-  top = bottom = left = right = 0;
-  if (!gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right))
-    return;
-
-  dialog->non_user_change = TRUE;
-  unit_widget_set (dialog->top_widget, _gtk_print_convert_to_mm (top, GTK_UNIT_POINTS));
-  unit_widget_set (dialog->bottom_widget, _gtk_print_convert_to_mm (bottom, GTK_UNIT_POINTS));
-  unit_widget_set (dialog->left_widget, _gtk_print_convert_to_mm (left, GTK_UNIT_POINTS));
-  unit_widget_set (dialog->right_widget, _gtk_print_convert_to_mm (right, GTK_UNIT_POINTS));
-  dialog->non_user_change = FALSE;
-
-  /* Only send one change */
-  unit_widget_changed (dialog);
-}
-
-static void
-get_margins_finished_callback (GtkPrinter               *printer,
-                               gboolean                  success,
-                               GtkCustomPaperUnixDialog *dialog)
-{
-  g_signal_handler_disconnect (dialog->request_details_printer,
-                               dialog->request_details_tag);
-  g_object_unref (dialog->request_details_printer);
-  dialog->request_details_tag = 0;
-  dialog->request_details_printer = NULL;
-
-  if (success)
-    set_margins_from_printer (dialog, printer);
-
-  gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
-}
-
-static void
-margins_from_printer_changed (GtkCustomPaperUnixDialog *dialog)
-{
-  guint selected;
-  GtkPrinter *printer;
-
-  if (dialog->request_details_tag)
-    {
-      g_signal_handler_disconnect (dialog->request_details_printer,
-                                   dialog->request_details_tag);
-      g_object_unref (dialog->request_details_printer);
-      dialog->request_details_printer = NULL;
-      dialog->request_details_tag = 0;
-    }
-
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
-  if (selected != 0)
-    {
-      GListModel *model;
-
-      model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
-      printer = g_list_model_get_item (model, selected);
-
-      if (printer)
-        {
-          if (gtk_printer_has_details (printer))
-            {
-              set_margins_from_printer (dialog, printer);
-              gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
-            }
-          else
-            {
-              dialog->request_details_printer = g_object_ref (printer);
-              dialog->request_details_tag =
-                g_signal_connect (printer, "details-acquired",
-                                  G_CALLBACK (get_margins_finished_callback), dialog);
-              gtk_printer_request_details (printer);
-            }
-
-          g_object_unref (printer);
-        }
-    }
-}
-
-static GtkWidget *
-wrap_in_frame (const char *label,
-               GtkWidget   *child)
-{
-  GtkWidget *frame, *label_widget;
-  char *bold_text;
-
-  label_widget = gtk_label_new (NULL);
-  gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
-  gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
-
-  bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
-  gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
-  g_free (bold_text);
-
-  frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-  gtk_box_append (GTK_BOX (frame), label_widget);
-
-  gtk_widget_set_margin_start (child, 12);
-  gtk_widget_set_halign (child, GTK_ALIGN_FILL);
-  gtk_widget_set_valign (child, GTK_ALIGN_FILL);
-
-  gtk_box_append (GTK_BOX (frame), child);
-
-  return frame;
-}
-
-static void
-setup_item (GtkSignalListItemFactory *factory,
-            GtkListItem              *item)
-{
-  gtk_list_item_set_child (item, gtk_editable_label_new (""));
-}
-
-static void
-label_changed (GObject     *object,
-               GParamSpec  *pspec,
-               GtkListItem *item)
-{
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-  const char *new_text;
-
-  page_setup = gtk_list_item_get_item (item);
-
-  new_text = gtk_editable_get_text (GTK_EDITABLE (object));
-
-  paper_size = gtk_paper_size_new_custom (new_text, new_text,
-                                          gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
-                                          gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM), GTK_UNIT_MM);
-  gtk_page_setup_set_paper_size (page_setup, paper_size);
-  gtk_paper_size_free (paper_size);
-}
-
-static void
-state_changed (GtkWidget     *item,
-               GtkStateFlags  old_state,
-               GtkWidget     *label)
-{
-  gboolean selected;
-
-  selected = (gtk_widget_get_state_flags (item) & GTK_STATE_FLAG_SELECTED) != 0;
-  gtk_editable_set_editable (GTK_EDITABLE (label), selected);
-}
-
-static void
-bind_item (GtkSignalListItemFactory *factory,
-           GtkListItem              *item)
-{
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-  GtkWidget *label;
-
-  page_setup = gtk_list_item_get_item (item);
-  label = gtk_list_item_get_child (item);
-
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-  gtk_editable_set_text (GTK_EDITABLE (label),
-                         gtk_paper_size_get_display_name (paper_size));
-  g_signal_connect (label, "notify::text",
-                    G_CALLBACK (label_changed), item);
-  g_signal_connect (gtk_widget_get_parent (label), "state-flags-changed",
-                    G_CALLBACK (state_changed), label);
-}
-
-static void
-unbind_item (GtkSignalListItemFactory *factory,
-             GtkListItem              *item)
-{
-  GtkWidget *label;
-
-  label = gtk_list_item_get_child (item);
-  g_signal_handlers_disconnect_by_func (label, label_changed, item);
-  g_signal_handlers_disconnect_by_func (gtk_widget_get_parent (label), state_changed, label);
-}
-
-static void
-setup_printer_item (GtkSignalListItemFactory *factory,
-                    GtkListItem              *item)
-{
-  GtkWidget *label;
-
-  label = gtk_label_new ("");
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_printer_item (GtkSignalListItemFactory *factory,
-                   GtkListItem              *item)
-{
-  GtkPrinter *printer;
-  GtkWidget *label;
-
-  printer = gtk_list_item_get_item (item);
-  label = gtk_list_item_get_child (item);
-
-  gtk_label_set_label (GTK_LABEL (label), gtk_printer_get_name (printer));
-}
-
-static void
-populate_dialog (GtkCustomPaperUnixDialog *dialog)
-{
-  GtkDialog *cpu_dialog = GTK_DIALOG (dialog);
-  GtkWidget *content_area;
-  GtkWidget *grid, *label, *widget, *frame, *combo;
-  GtkWidget *hbox, *vbox, *listview, *scrolled, *toolbar, *button;
-  GtkUnit user_units;
-  GtkSelectionModel *model;
-  GtkListItemFactory *factory;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  content_area = gtk_dialog_get_content_area (cpu_dialog);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-  gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
-
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
-  gtk_widget_set_margin_start (hbox, 20);
-  gtk_widget_set_margin_end (hbox, 20);
-  gtk_widget_set_margin_top (hbox, 20);
-  gtk_widget_set_margin_bottom (hbox, 20);
-  gtk_box_append (GTK_BOX (content_area), hbox);
-
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-  gtk_box_append (GTK_BOX (hbox), vbox);
-
-  scrolled = gtk_scrolled_window_new ();
-  gtk_widget_set_vexpand (scrolled, TRUE);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
-                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-  gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
-  gtk_box_append (GTK_BOX (vbox), scrolled);
-
-  model = GTK_SELECTION_MODEL (gtk_single_selection_new (g_object_ref (G_LIST_MODEL (dialog->custom_paper_list))));
-  g_signal_connect (model, "notify::selected", G_CALLBACK (selected_custom_paper_changed), dialog);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
-  g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
-
-  listview = gtk_list_view_new (model, factory);
-  gtk_widget_set_size_request (listview, 140, -1);
-
-  dialog->listview = listview;
-
-  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), listview);
-
-  toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
-  gtk_widget_add_css_class (toolbar, "linked");
-
-  gtk_box_append (GTK_BOX (vbox), toolbar);
-
-  button = gtk_button_new_from_icon_name ("list-add-symbolic");
-  g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), dialog);
-
-  gtk_box_append (GTK_BOX (toolbar), button);
-
-  button = gtk_button_new_from_icon_name ("list-remove-symbolic");
-  g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), dialog);
-
-  gtk_box_append (GTK_BOX (toolbar), button);
-
-  user_units = _gtk_print_get_default_user_units ();
-
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
-  dialog->values_box = vbox;
-  gtk_box_append (GTK_BOX (hbox), vbox);
-
-  grid = gtk_grid_new ();
-
-  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
-  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-
-  label = gtk_label_new_with_mnemonic (_("_Width:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->width_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
-
-  label = gtk_label_new_with_mnemonic (_("_Height:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->height_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
-
-  frame = wrap_in_frame (_("Paper Size"), grid);
-  gtk_box_append (GTK_BOX (vbox), frame);
-
-  grid = gtk_grid_new ();
-  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
-  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-
-  label = gtk_label_new_with_mnemonic (_("_Top:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->top_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
-
-  label = gtk_label_new_with_mnemonic (_("_Bottom:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->bottom_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
-
-  label = gtk_label_new_with_mnemonic (_("_Left:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->left_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 2, 1, 1);
-
-  label = gtk_label_new_with_mnemonic (_("_Right:"));
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-  gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
-
-  widget = new_unit_widget (dialog, user_units, label);
-  dialog->right_widget = widget;
-  gtk_grid_attach (GTK_GRID (grid), widget, 1, 3, 1, 1);
-
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-  gtk_grid_attach (GTK_GRID (grid), hbox, 0, 4, 2, 1);
-
-  combo = gtk_drop_down_new (g_object_ref (dialog->printer_list), NULL);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (combo), factory);
-  g_object_unref (factory);
-
-  dialog->printer_combo = combo;
-
-  dialog->printer_inserted_tag =
-    g_signal_connect_swapped (dialog->printer_list, "items-changed",
-                              G_CALLBACK (update_combo_sensitivity_from_printers), dialog);
-  update_combo_sensitivity_from_printers (dialog);
-
-  gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), 0);
-  gtk_box_append (GTK_BOX (hbox), combo);
-
-  g_signal_connect_swapped (combo, "notify::selected",
-                            G_CALLBACK (margins_from_printer_changed), dialog);
-
-  frame = wrap_in_frame (_("Paper Margins"), grid);
-  gtk_box_append (GTK_BOX (vbox), frame);
-
-  update_custom_widgets_from_list (dialog);
-
-  if (g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)) == 0)
-    add_custom_paper (dialog);
-
-  load_print_backends (dialog);
-}
diff --git a/gtk/gtkcustompaperunixdialog.h b/gtk/gtkcustompaperunixdialog.h
deleted file mode 100644 (file)
index 630737a..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* GtkCustomPaperUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG                  (gtk_custom_paper_unix_dialog_get_type ())
-#define GTK_CUSTOM_PAPER_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG, GtkCustomPaperUnixDialog))
-#define GTK_IS_CUSTOM_PAPER_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG))
-
-typedef struct _GtkCustomPaperUnixDialog         GtkCustomPaperUnixDialog;
-
-GDK_AVAILABLE_IN_ALL
-GType             gtk_custom_paper_unix_dialog_get_type           (void) G_GNUC_CONST;
-GtkWidget *       _gtk_custom_paper_unix_dialog_new                (GtkWindow   *parent,
-                                                                    const char *title);
-GtkUnit           _gtk_print_get_default_user_units                (void);
-void               gtk_print_load_custom_papers                    (GListStore *store);
-GList *           _gtk_load_custom_papers                          (void);
-
-
-G_END_DECLS
-
index 9c07e3d652ea14a9c97d2f8f7abfc3806544bcdb..573f250d8b2b5accf268a14d32c77d97298dcec1 100644 (file)
@@ -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 (file)
index c0de95d..0000000
+++ /dev/null
@@ -1,950 +0,0 @@
-/* GtkPageSetupUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007, 2008 Christian Persch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "config.h"
-#include <string.h>
-#include <locale.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-
-#include "gtkbutton.h"
-#include "gtkscrolledwindow.h"
-#include "gtkcheckbutton.h"
-#include "gtklabel.h"
-#include "gtkgrid.h"
-
-#include "gtkpagesetupunixdialog.h"
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "print/gtkpapersize.h"
-#include "gtkprintutilsprivate.h"
-#include "deprecated/gtkdialogprivate.h"
-
-/**
- * GtkPageSetupUnixDialog:
- *
- * `GtkPageSetupUnixDialog` implements a page setup dialog for platforms
- * which don’t provide a native page setup dialog, like Unix.
- *
- * ![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 ("<b>%s</b>\n%s", name, location ? location : "");
-  gtk_label_set_markup (GTK_LABEL (label), str);
-  g_free (str);
-}
-
-static void
-gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
-{
-  GtkListItemFactory *factory;
-  GListStore *store;
-  GListModel *paper_size_list;
-  GtkPrinter *printer;
-  GListStore *printer_list;
-  GListStore *printer_list_list;
-  GListModel *full_list;
-  GtkFilter *filter;
-  GtkPageSetup *page_setup;
-
-  dialog->internal_change = TRUE;
-  dialog->print_backends = NULL;
-
-  gtk_widget_init_template (GTK_WIDGET (dialog));
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
-  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                          _("_Cancel"), GTK_RESPONSE_CANCEL,
-                          _("_Apply"), GTK_RESPONSE_OK,
-                          NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-  dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  page_setup = gtk_page_setup_new ();
-  g_list_store_append (dialog->manage_papers_list, page_setup);
-  g_object_unref (page_setup);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
-  g_object_unref (factory);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
-  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
-  g_object_unref (factory);
-
-  store = g_list_store_new (G_TYPE_LIST_MODEL);
-  g_list_store_append (store, dialog->page_setup_list);
-  g_list_store_append (store, dialog->custom_paper_list);
-  g_list_store_append (store, dialog->manage_papers_list);
-  paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
-  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
-  g_object_unref (paper_size_list);
-
-  /* Do this in code, we want the translatable strings without the markup */
-  printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
-  printer_list = g_list_store_new (GTK_TYPE_PRINTER);
-  printer = gtk_printer_new (_("Any Printer"), NULL, FALSE);
-  gtk_printer_set_location (printer, _("For portable documents"));
-  g_list_store_append (printer_list, printer);
-  g_object_unref (printer);
-  g_list_store_append (printer_list_list, printer_list);
-  g_object_unref (printer_list);
-
-  full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
-
-  filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
-  dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->printer_combo), factory);
-  g_object_unref (factory);
-
-  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->printer_combo), dialog->printer_list);
-  printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
-
-  /* Load data */
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-  load_print_backends (dialog);
-  dialog->internal_change = FALSE;
-}
-
-static void
-gtk_page_setup_unix_dialog_finalize (GObject *object)
-{
-  GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
-  GList *node;
-
-  if (dialog->request_details_tag)
-    {
-      g_signal_handler_disconnect (dialog->request_details_printer,
-                                   dialog->request_details_tag);
-      g_object_unref (dialog->request_details_printer);
-      dialog->request_details_printer = NULL;
-      dialog->request_details_tag = 0;
-    }
-
-  g_clear_object (&dialog->printer_list);
-  g_clear_object (&dialog->page_setup_list);
-  g_clear_object (&dialog->custom_paper_list);
-  g_clear_object (&dialog->manage_papers_list);
-
-  if (dialog->print_settings)
-    {
-      g_object_unref (dialog->print_settings);
-      dialog->print_settings = NULL;
-    }
-
-  for (node = dialog->print_backends; node != NULL; node = node->next)
-    gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
-  g_list_free_full (dialog->print_backends, g_object_unref);
-  dialog->print_backends = NULL;
-
-  G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
-}
-
-static void
-load_print_backends (GtkPageSetupUnixDialog *dialog)
-{
-  GListModel *full_list;
-  GListStore *printer_list_list;
-  GList *node;
-
-  full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
-  printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
-
-  if (g_module_supported ())
-    dialog->print_backends = gtk_print_backend_load_modules ();
-
-  for (node = dialog->print_backends; node != NULL; node = node->next)
-    {
-      GtkPrintBackend *backend = node->data;
-      g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
-    }
-}
-
-static GtkPageSetup *
-get_current_page_setup (GtkPageSetupUnixDialog *dialog)
-{
-  guint selected;
-  GListModel *model;
-
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->paper_size_combo));
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
-  if (selected != GTK_INVALID_LIST_POSITION)
-    return g_list_model_get_item (model, selected);
-
-  return gtk_page_setup_new ();
-}
-
-static gboolean
-page_setup_is_equal (GtkPageSetup *a,
-                     GtkPageSetup *b)
-{
-  return
-    gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
-                             gtk_page_setup_get_paper_size (b)) &&
-    gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
-}
-
-static gboolean
-page_setup_is_same_size (GtkPageSetup *a,
-                         GtkPageSetup *b)
-{
-  return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
-                                  gtk_page_setup_get_paper_size (b));
-}
-
-static gboolean
-set_paper_size (GtkPageSetupUnixDialog *dialog,
-                GtkPageSetup           *page_setup,
-                gboolean                size_only,
-                gboolean                add_item)
-{
-  GListModel *model;
-  GtkPageSetup *list_page_setup;
-  guint i;
-
-  if (page_setup == NULL)
-    return FALSE;
-
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
-  for (i = 0; i < g_list_model_get_n_items (model); i++)
-    {
-      list_page_setup = g_list_model_get_item (model, i);
-      if (list_page_setup == NULL)
-        continue;
-
-      if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
-          (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
-        {
-          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
-          g_object_unref (list_page_setup);
-          return TRUE;
-        }
-
-      g_object_unref (list_page_setup);
-    }
-
-  if (add_item)
-    {
-      i = g_list_model_get_n_items (model);
-      g_list_store_append (dialog->page_setup_list, page_setup);
-      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
-                               GtkPrinter             *printer)
-{
-  GList *list, *l;
-  GtkPageSetup *current_page_setup, *page_setup;
-  GtkPaperSize *paper_size;
-  int i;
-
-  g_list_store_remove_all (dialog->page_setup_list);
-
-  if (printer == NULL)
-    {
-      for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
-        {
-          page_setup = gtk_page_setup_new ();
-          paper_size = gtk_paper_size_new (common_paper_sizes[i]);
-          gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
-          gtk_paper_size_free (paper_size);
-
-          g_list_store_append (dialog->page_setup_list, page_setup);
-          g_object_unref (page_setup);
-        }
-    }
-  else
-    {
-      list = gtk_printer_list_papers (printer);
-      /* TODO: We should really sort this list so interesting size
-         are at the top */
-      for (l = list; l != NULL; l = l->next)
-        {
-          page_setup = l->data;
-          g_list_store_append (dialog->page_setup_list, page_setup);
-          g_object_unref (page_setup);
-        }
-      g_list_free (list);
-    }
-
-  current_page_setup = NULL;
-
-  /* When selecting a different printer, select its default paper size */
-  if (printer != NULL)
-    current_page_setup = gtk_printer_get_default_page_size (printer);
-
-  if (current_page_setup == NULL)
-    current_page_setup = get_current_page_setup (dialog);
-
-  if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
-    set_paper_size (dialog, current_page_setup, TRUE, TRUE);
-
-  if (current_page_setup)
-    g_object_unref (current_page_setup);
-}
-
-static void
-printer_changed_finished_callback (GtkPrinter             *printer,
-                                   gboolean                success,
-                                   GtkPageSetupUnixDialog *dialog)
-{
-  g_signal_handler_disconnect (dialog->request_details_printer,
-                               dialog->request_details_tag);
-  g_object_unref (dialog->request_details_printer);
-  dialog->request_details_tag = 0;
-  dialog->request_details_printer = NULL;
-
-  if (success)
-    fill_paper_sizes_from_printer (dialog, printer);
-
-}
-
-static void
-printer_changed_callback (GtkDropDown            *combo_box,
-                          GParamSpec             *pspec,
-                          GtkPageSetupUnixDialog *dialog)
-{
-  GtkPrinter *printer;
-  guint selected;
-
-  if (dialog->request_details_tag)
-    {
-      g_signal_handler_disconnect (dialog->request_details_printer,
-                                   dialog->request_details_tag);
-      g_object_unref (dialog->request_details_printer);
-      dialog->request_details_printer = NULL;
-      dialog->request_details_tag = 0;
-    }
-
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
-  if (selected != GTK_INVALID_LIST_POSITION)
-    {
-      GListModel *model;
-
-      model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
-      printer = g_list_model_get_item (model, selected);
-      if (strcmp (gtk_printer_get_name (printer), _("Any Printer")) == 0)
-        g_clear_object (&printer);
-
-      if (printer == NULL ||
-          gtk_printer_has_details (printer))
-        fill_paper_sizes_from_printer (dialog, printer);
-      else
-        {
-          dialog->request_details_printer = g_object_ref (printer);
-          dialog->request_details_tag =
-            g_signal_connect (printer, "details-acquired",
-                              G_CALLBACK (printer_changed_finished_callback), dialog);
-          gtk_printer_request_details (printer);
-        }
-
-      if (printer)
-        g_object_unref (printer);
-
-      if (dialog->print_settings)
-        {
-          const char *name = NULL;
-
-          if (printer)
-            name = gtk_printer_get_name (printer);
-
-          gtk_print_settings_set (dialog->print_settings,
-                                  "format-for-printer", name);
-        }
-    }
-}
-
-/* We do this munging because we don't want to show zero digits
-   after the decimal point, and not to many such digits if they
-   are nonzero. I wish printf let you specify max precision for %f... */
-static char *
-double_to_string (double d,
-                  GtkUnit unit)
-{
-  char *val, *p;
-  struct lconv *locale_data;
-  const char *decimal_point;
-  int decimal_point_len;
-
-  locale_data = localeconv ();
-  decimal_point = locale_data->decimal_point;
-  decimal_point_len = strlen (decimal_point);
-
-  /* Max two decimal digits for inch, max one for mm */
-  if (unit == GTK_UNIT_INCH)
-    val = g_strdup_printf ("%.2f", d);
-  else
-    val = g_strdup_printf ("%.1f", d);
-
-  if (strstr (val, decimal_point))
-    {
-      p = val + strlen (val) - 1;
-      while (*p == '0')
-        p--;
-      if (p - val + 1 >= decimal_point_len &&
-          strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
-        p -= decimal_point_len;
-      p[1] = '\0';
-    }
-
-  return val;
-}
-
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
-                                 int        response_id,
-                                 gpointer   user_data)
-{
-  GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (user_data);
-  GtkPageSetup *last_page_setup;
-
-  dialog->internal_change = TRUE;
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-  printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
-  dialog->internal_change = FALSE;
-
-  if (dialog->last_setup)
-    last_page_setup = g_object_ref (dialog->last_setup);
-  else
-    last_page_setup = gtk_page_setup_new (); /* "good" default */
-  set_paper_size (dialog, last_page_setup, FALSE, TRUE);
-  g_object_unref (last_page_setup);
-
-  gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
-}
-
-static void
-paper_size_changed (GtkDropDown            *combo_box,
-                    GParamSpec             *pspec,
-                    GtkPageSetupUnixDialog *dialog)
-{
-  GtkPageSetup *page_setup, *last_page_setup;
-  guint selected;
-  GtkUnit unit;
-  char *str, *w, *h;
-  char *top, *bottom, *left, *right;
-  GtkLabel *label;
-  const char *unit_str;
-
-  if (dialog->internal_change)
-    return;
-
-  label = GTK_LABEL (dialog->paper_size_label);
-
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
-  if (selected != GTK_INVALID_LIST_POSITION)
-    {
-      GListModel *papers, *model;
-
-      papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
-      page_setup = g_list_model_get_item (papers, selected);
-      model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
-
-      if (model == G_LIST_MODEL (dialog->manage_papers_list))
-        {
-          GtkWidget *custom_paper_dialog;
-
-          /* Change from "manage" menu item to last value */
-          if (dialog->last_setup)
-            last_page_setup = g_object_ref (dialog->last_setup);
-          else
-            last_page_setup = gtk_page_setup_new (); /* "good" default */
-          set_paper_size (dialog, last_page_setup, FALSE, TRUE);
-          g_object_unref (last_page_setup);
-
-          /* And show the custom paper dialog */
-          custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), NULL);
-          g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
-          gtk_window_present (GTK_WINDOW (custom_paper_dialog));
-
-          g_object_unref (page_setup);
-
-          return;
-        }
-
-      if (dialog->last_setup)
-        g_object_unref (dialog->last_setup);
-
-      dialog->last_setup = g_object_ref (page_setup);
-
-      unit = _gtk_print_get_default_user_units ();
-
-      if (unit == GTK_UNIT_MM)
-        unit_str = _("mm");
-      else
-        unit_str = _("inch");
-
-      w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
-                            unit);
-      h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
-                            unit);
-      str = g_strdup_printf ("%s × %s %s", w, h, unit_str);
-      g_free (w);
-      g_free (h);
-
-      gtk_label_set_text (label, str);
-      g_free (str);
-
-      top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
-      bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
-      left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
-      right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
-
-      str = g_strdup_printf (_("Margins:\n"
-                               " Left: %s %s\n"
-                               " Right: %s %s\n"
-                               " Top: %s %s\n"
-                               " Bottom: %s %s"
-                               ),
-                             left, unit_str,
-                             right, unit_str,
-                             top, unit_str,
-                             bottom, unit_str);
-      g_free (top);
-      g_free (bottom);
-      g_free (left);
-      g_free (right);
-
-      gtk_widget_set_tooltip_text (dialog->paper_size_label, str);
-      g_free (str);
-
-      g_object_unref (page_setup);
-    }
-  else
-    {
-      gtk_label_set_text (label, "");
-      gtk_widget_set_tooltip_text (dialog->paper_size_label, NULL);
-      if (dialog->last_setup)
-        g_object_unref (dialog->last_setup);
-      dialog->last_setup = NULL;
-    }
-}
-
-/**
- * gtk_page_setup_unix_dialog_new:
- * @title: (nullable): the title of the dialog
- * @parent: (nullable): transient parent of the dialog
- *
- * Creates a new page setup dialog.
- *
- * Returns: the new `GtkPageSetupUnixDialog`
- */
-GtkWidget *
-gtk_page_setup_unix_dialog_new (const char *title,
-                                GtkWindow   *parent)
-{
-  GtkWidget *result;
-
-  if (title == NULL)
-    title = _("Page Setup");
-
-  result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
-                         "title", title,
-                         NULL);
-
-  if (parent)
-    gtk_window_set_transient_for (GTK_WINDOW (result), parent);
-
-  return result;
-}
-
-static GtkPageOrientation
-get_orientation (GtkPageSetupUnixDialog *dialog)
-{
-  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->portrait_radio)))
-    return GTK_PAGE_ORIENTATION_PORTRAIT;
-  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->landscape_radio)))
-    return GTK_PAGE_ORIENTATION_LANDSCAPE;
-  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio)))
-    return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
-  return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
-}
-
-static void
-set_orientation (GtkPageSetupUnixDialog *dialog,
-                 GtkPageOrientation      orientation)
-{
-  switch (orientation)
-    {
-    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_portrait_radio), TRUE);
-      break;
-    case GTK_PAGE_ORIENTATION_PORTRAIT:
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->portrait_radio), TRUE);
-      break;
-    case GTK_PAGE_ORIENTATION_LANDSCAPE:
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->landscape_radio), TRUE);
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio), TRUE);
-      break;
-    default:
-      break;
-    }
-}
-
-/**
- * gtk_page_setup_unix_dialog_set_page_setup:
- * @dialog: a `GtkPageSetupUnixDialog`
- * @page_setup: a `GtkPageSetup`
- *
- * Sets the `GtkPageSetup` from which the page setup
- * dialog takes its values.
- */
-void
-gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
-                                           GtkPageSetup           *page_setup)
-{
-  if (page_setup)
-    {
-      set_paper_size (dialog, page_setup, FALSE, TRUE);
-      set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
-    }
-}
-
-/**
- * gtk_page_setup_unix_dialog_get_page_setup:
- * @dialog: a `GtkPageSetupUnixDialog`
- *
- * Gets the currently selected page setup from the dialog.
- *
- * Returns: (transfer none): the current page setup
- */
-GtkPageSetup *
-gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
-{
-  GtkPageSetup *page_setup;
-
-  page_setup = get_current_page_setup (dialog);
-
-  gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
-
-  return page_setup;
-}
-
-static gboolean
-set_active_printer (GtkPageSetupUnixDialog *dialog,
-                    const char             *printer_name)
-{
-  guint i, n;
-  GtkPrinter *printer;
-
-  if (!printer_name)
-    return FALSE;
-
-  for (i = 0, n = g_list_model_get_n_items (dialog->printer_list); i < n; i++)
-    {
-      printer = g_list_model_get_item (dialog->printer_list, i);
-
-      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
-        {
-          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), i);
-          g_object_unref (printer);
-
-          return TRUE;
-        }
-
-      g_object_unref (printer);
-    }
-
-  return FALSE;
-}
-
-/**
- * gtk_page_setup_unix_dialog_set_print_settings:
- * @dialog: a `GtkPageSetupUnixDialog`
- * @print_settings: (nullable): a `GtkPrintSettings`
- *
- * Sets the `GtkPrintSettings` from which the page setup dialog
- * takes its values.
- */
-void
-gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
-                                               GtkPrintSettings       *print_settings)
-{
-  const char *format_for_printer;
-
-  if (dialog->print_settings == print_settings) return;
-
-  if (dialog->print_settings)
-    g_object_unref (dialog->print_settings);
-
-  dialog->print_settings = print_settings;
-
-  if (print_settings)
-    {
-      g_object_ref (print_settings);
-
-      format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
-
-      /* Set printer if in list, otherwise set when
-       * that printer is added
-       */
-      set_active_printer (dialog, format_for_printer);
-    }
-}
-
-/**
- * gtk_page_setup_unix_dialog_get_print_settings:
- * @dialog: a `GtkPageSetupUnixDialog`
- *
- * Gets the current print settings from the dialog.
- *
- * Returns: (transfer none) (nullable): the current print settings
- **/
-GtkPrintSettings *
-gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
-{
-  return dialog->print_settings;
-}
diff --git a/gtk/gtkpagesetupunixdialog.h b/gtk/gtkpagesetupunixdialog.h
deleted file mode 100644 (file)
index 84a42cb..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* GtkPageSetupUnixDialog
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PAGE_SETUP_UNIX_DIALOG                  (gtk_page_setup_unix_dialog_get_type ())
-#define GTK_PAGE_SETUP_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialog))
-#define GTK_IS_PAGE_SETUP_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG))
-
-
-typedef struct _GtkPageSetupUnixDialog GtkPageSetupUnixDialog;
-
-
-GDK_AVAILABLE_IN_ALL
-GType            gtk_page_setup_unix_dialog_get_type           (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkWidget *       gtk_page_setup_unix_dialog_new                (const char             *title,
-                                                                GtkWindow              *parent);
-GDK_AVAILABLE_IN_ALL
-void              gtk_page_setup_unix_dialog_set_page_setup     (GtkPageSetupUnixDialog *dialog,
-                                                                GtkPageSetup           *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup *    gtk_page_setup_unix_dialog_get_page_setup     (GtkPageSetupUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void              gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
-                                                                GtkPrintSettings       *print_settings);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings *gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprint-win32.c b/gtk/gtkprint-win32.c
deleted file mode 100644 (file)
index 76b1d69..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _MSC_VER
-#ifndef _WIN32_WINNT
-/* Vista or newer */
-#define _WIN32_WINNT 0x0600
-#endif
-#ifndef WINVER
-#define WINVER _WIN32_WINNT
-#endif
-#endif
-
-#include "config.h"
-#include "gtkprint-win32.h"
-
-void
-gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames)
-{
-  g_free (devnames->driver);
-  g_free (devnames->device);
-  g_free (devnames->output);
-  g_free (devnames);
-}
-
-GtkPrintWin32Devnames *
-gtk_print_win32_devnames_from_win32 (HGLOBAL global)
-{
-  LPDEVNAMES win = GlobalLock (global);
-  gunichar2 *data = (gunichar2 *)win;
-  GtkPrintWin32Devnames *devnames = g_new (GtkPrintWin32Devnames, 1);
-  
-  devnames->driver = g_utf16_to_utf8 (data + win->wDriverOffset, 
-                                     -1, NULL, NULL, NULL);
-  devnames->device = g_utf16_to_utf8 (data + win->wDeviceOffset, 
-                                     -1, NULL, NULL, NULL);
-  devnames->output = g_utf16_to_utf8 (data + win->wOutputOffset, 
-                                     -1, NULL, NULL, NULL);
-  devnames->flags = win->wDefault;
-  
-  GlobalUnlock (global);
-
-  return devnames;
-}
-
-HGLOBAL 
-gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames)
-{
-  HGLOBAL global;
-  LPDEVNAMES windevnames;
-  gunichar2 *data;
-  gunichar2 *driver, *device, *output;
-  glong driver_len, device_len, output_len;
-  int i;
-
-  driver = g_utf8_to_utf16 (devnames->driver, -1, NULL, &driver_len, NULL);
-  device = g_utf8_to_utf16 (devnames->device, -1, NULL, &device_len, NULL);
-  output = g_utf8_to_utf16 (devnames->output, -1, NULL, &output_len, NULL);
-
-  global = GlobalAlloc (GMEM_MOVEABLE, 
-                       sizeof (DEVNAMES) + 
-                       (driver_len + 1) * 2 + 
-                       (device_len + 1) * 2 +
-                       (output_len + 1) * 2);
-
-  windevnames = GlobalLock (global);
-  data = (gunichar2 *)windevnames;
-  i = sizeof(DEVNAMES) / sizeof (gunichar2);
-
-  windevnames->wDriverOffset = i;
-  memcpy (data + i, driver, (driver_len + 1) * sizeof (gunichar2));
-  i += driver_len + 1;
-  windevnames->wDeviceOffset = i;
-  memcpy (data + i, device, (device_len + 1) * sizeof (gunichar2));
-  i += device_len + 1;
-  windevnames->wOutputOffset = i;
-  memcpy (data + i, output, (output_len + 1) * sizeof (gunichar2));
-  i += output_len + 1;
-  windevnames->wDefault = devnames->flags;
-  GlobalUnlock (global);
-
-  g_free (driver);
-  g_free (device);
-  g_free (output);
-
-  return global;
-}
-
-HGLOBAL 
-gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer_name)
-{
-  HGLOBAL global;
-  GtkPrintWin32Devnames *devnames;
-
-  devnames = gtk_print_win32_devnames_from_printer_name(printer_name);
-  if (devnames)
-    {
-      global = gtk_print_win32_devnames_to_win32 (devnames);
-      gtk_print_win32_devnames_free (devnames);
-    }
-  else
-    global = NULL;
-
-  return global;
-}
-
-/*
- * Used to get printer device information from a printer name.  This
- * can fail if the user has no right to read printer properties, so
- * this function can return NULL.
- */
-GtkPrintWin32Devnames *
-gtk_print_win32_devnames_from_printer_name (const char *printer_name)
-{
-  HANDLE hprinter;
-  gunichar2* win32_printer_name;
-  GtkPrintWin32Devnames *devnames;
-
-  win32_printer_name = g_utf8_to_utf16 (printer_name, -1, NULL, NULL, NULL);
-  if (OpenPrinterW (win32_printer_name, &hprinter, NULL))
-    {
-      DWORD needed;
-      PRINTER_INFO_2W* printer_info;
-
-      GetPrinterW (hprinter, 2, NULL, 0, &needed);
-      printer_info = (PRINTER_INFO_2W* )g_malloc ((gsize) needed);
-      GetPrinterW (hprinter, 2, (LPBYTE) printer_info, needed, &needed);
-      devnames = g_new (GtkPrintWin32Devnames, 1);
-      devnames->driver = g_utf16_to_utf8 (printer_info->pDriverName, -1, NULL, NULL, NULL);
-      devnames->device = g_strdup (printer_name);
-      devnames->output = g_utf16_to_utf8 (printer_info->pPortName, -1, NULL, NULL, NULL);
-      devnames->flags  = 0;
-      ClosePrinter (hprinter);
-      g_free (printer_info);
-    }
-  else
-    {
-      /* Could not open printer */
-      devnames = NULL;
-    }
-  g_free (win32_printer_name);
-
-  return devnames;
-}
diff --git a/gtk/gtkprint-win32.h b/gtk/gtkprint-win32.h
deleted file mode 100644 (file)
index 626e15d..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "win32/gdkwin32.h"
-
-G_BEGIN_DECLS
-
-#ifndef START_PAGE_GENERAL
-#define START_PAGE_GENERAL 0xffffffff
-#endif
-
-#ifndef PD_RESULT_CANCEL
-#define PD_RESULT_CANCEL  0
-#define PD_RESULT_PRINT  1
-#define PD_RESULT_APPLY  2
-#endif
-
-#ifndef PD_NOCURRENTPAGE
-#define PD_NOCURRENTPAGE  0x00800000
-#endif
-
-#ifndef PD_CURRENTPAGE
-#define PD_CURRENTPAGE  0x00400000
-#endif
-
-typedef struct {
-  char *driver;
-  char *device;
-  char *output;
-  int flags;
-} GtkPrintWin32Devnames;
-
-GDK_AVAILABLE_IN_ALL
-void gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames);
-GDK_AVAILABLE_IN_ALL
-GtkPrintWin32Devnames *gtk_print_win32_devnames_from_win32 (HGLOBAL global);
-GDK_AVAILABLE_IN_ALL
-GtkPrintWin32Devnames *gtk_print_win32_devnames_from_printer_name (const char *printer);
-GDK_AVAILABLE_IN_ALL
-HGLOBAL gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames);
-GDK_AVAILABLE_IN_ALL
-HGLOBAL gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprintbackend.c b/gtk/gtkprintbackend.c
deleted file mode 100644 (file)
index 1fd4c35..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <string.h>
-
-#include <gmodule.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkdebug.h"
-#include "gtkmodulesprivate.h"
-#include "gtkmarshalers.h"
-#include "gtkprivate.h"
-#include "gtkprintbackendprivate.h"
-
-
-static void gtk_print_backend_finalize     (GObject      *object);
-static void gtk_print_backend_dispose      (GObject      *object);
-static void gtk_print_backend_set_property (GObject      *object,
-                                            guint         prop_id,
-                                            const GValue *value,
-                                            GParamSpec   *pspec);
-static void gtk_print_backend_get_property (GObject      *object,
-                                            guint         prop_id,
-                                            GValue       *value,
-                                            GParamSpec   *pspec);
-
-struct _GtkPrintBackendPrivate
-{
-  GListStore *printers;
-  guint printer_list_requested : 1;
-  guint printer_list_done : 1;
-  GtkPrintBackendStatus status;
-  char **auth_info_required;
-  char **auth_info;
-  gboolean store_auth_info;
-};
-
-enum {
-  PRINTER_LIST_CHANGED,
-  PRINTER_LIST_DONE,
-  PRINTER_ADDED,
-  PRINTER_REMOVED,
-  PRINTER_STATUS_CHANGED,
-  REQUEST_PASSWORD,
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-enum 
-{ 
-  PROP_ZERO,
-  PROP_STATUS
-};
-
-static GObjectClass *backend_parent_class;
-
-GQuark
-gtk_print_backend_error_quark (void)
-{
-  static GQuark quark = 0;
-  if (quark == 0)
-    quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
-  return quark;
-}
-
-void
-gtk_print_backends_init (void)
-{
-  GIOExtensionPoint *ep;
-  GIOModuleScope *scope;
-  char **paths;
-  int i;
-
-  GTK_DEBUG (MODULES, "Registering extension point %s", GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
-
-  ep = g_io_extension_point_register (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
-  g_io_extension_point_set_required_type (ep, GTK_TYPE_PRINT_BACKEND);
-
-  scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
-
-  paths = _gtk_get_module_path ("printbackends");
-  for (i = 0; paths[i]; i++)
-    {
-      GTK_DEBUG (MODULES, "Scanning io modules in %s", paths[i]);
-      g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
-    }
-  g_strfreev (paths);
-
-  g_io_module_scope_free (scope);
-
-  if (GTK_DEBUG_CHECK (MODULES))
-    {
-      GList *list, *l;
-
-      list = g_io_extension_point_get_extensions (ep);
-      for (l = list; l; l = l->next)
-        {
-          GIOExtension *ext = l->data;
-          g_print ("extension: %s: type %s\n",
-                   g_io_extension_get_name (ext),
-                   g_type_name (g_io_extension_get_type (ext)));
-        }
-    }
-}
-
-/**
- * gtk_print_backend_load_modules:
- *
- * Returns: (element-type GtkPrintBackend) (transfer container):
- */
-GList *
-gtk_print_backend_load_modules (void)
-{
-  GList *result;
-  GtkPrintBackend *backend;
-  char *setting;
-  char **backends;
-  int i;
-  GtkSettings *settings;
-  GIOExtensionPoint *ep;
-
-  result = NULL;
-
-  ep = g_io_extension_point_lookup (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
-
-  settings = gtk_settings_get_default ();
-  if (settings)
-    g_object_get (settings, "gtk-print-backends", &setting, NULL);
-  else
-    setting = g_strdup (GTK_PRINT_BACKENDS);
-
-  backends = g_strsplit (setting, ",", -1);
-
-  for (i = 0; backends[i]; i++)
-    {
-      GIOExtension *ext;
-      GType type;
-
-      ext = g_io_extension_point_get_extension_by_name (ep, backends[i]);
-      if (!ext)
-        continue;
-
-      GTK_DEBUG (PRINTING, "Found %s print backend", backends[i]);
-
-      type = g_io_extension_get_type (ext);
-      backend = g_object_new (type, NULL);
-      result = g_list_append (result, backend);
-    }
-
-  g_strfreev (backends);
-  g_free (setting);
-
-  return result;
-}
-
-/*****************************************
- *             GtkPrintBackend           *
- *****************************************/
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
-
-static void                 fallback_printer_request_details       (GtkPrinter          *printer);
-static gboolean             fallback_printer_mark_conflicts        (GtkPrinter          *printer,
-                                                                   GtkPrinterOptionSet *options);
-static gboolean             fallback_printer_get_hard_margins      (GtkPrinter          *printer,
-                                                                    double              *top,
-                                                                    double              *bottom,
-                                                                    double              *left,
-                                                                    double              *right);
-static gboolean             fallback_printer_get_hard_margins_for_paper_size (GtkPrinter          *printer,
-                                                                             GtkPaperSize        *paper_size,
-                                                                             double              *top,
-                                                                             double              *bottom,
-                                                                             double              *left,
-                                                                             double              *right);
-static GList *              fallback_printer_list_papers           (GtkPrinter          *printer);
-static GtkPageSetup *       fallback_printer_get_default_page_size (GtkPrinter          *printer);
-static GtkPrintCapabilities fallback_printer_get_capabilities      (GtkPrinter          *printer);
-static void                 request_password                       (GtkPrintBackend     *backend,
-                                                                    gpointer             auth_info_required,
-                                                                    gpointer             auth_info_default,
-                                                                    gpointer             auth_info_display,
-                                                                    gpointer             auth_info_visible,
-                                                                    const char          *prompt,
-                                                                    gboolean             can_store_auth_info);
-
-static void
-gtk_print_backend_set_property (GObject      *object,
-                                guint         prop_id,
-                                const GValue *value,
-                                GParamSpec   *pspec)
-{
-  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
-  GtkPrintBackendPrivate *priv = backend->priv;
-
-  switch (prop_id)
-    {
-    case PROP_STATUS:
-      priv->status = g_value_get_int (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_print_backend_get_property (GObject    *object,
-                                guint       prop_id,
-                                GValue     *value,
-                                GParamSpec *pspec)
-{
-  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
-  GtkPrintBackendPrivate *priv = backend->priv;
-
-  switch (prop_id)
-    {
-    case PROP_STATUS:
-      g_value_set_int (value, priv->status);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_print_backend_class_init (GtkPrintBackendClass *class)
-{
-  GObjectClass *object_class;
-  object_class = (GObjectClass *) class;
-
-  backend_parent_class = g_type_class_peek_parent (class);
-  
-  object_class->finalize = gtk_print_backend_finalize;
-  object_class->dispose = gtk_print_backend_dispose;
-  object_class->set_property = gtk_print_backend_set_property;
-  object_class->get_property = gtk_print_backend_get_property;
-
-  class->printer_request_details = fallback_printer_request_details;
-  class->printer_mark_conflicts = fallback_printer_mark_conflicts;
-  class->printer_get_hard_margins = fallback_printer_get_hard_margins;
-  class->printer_get_hard_margins_for_paper_size = fallback_printer_get_hard_margins_for_paper_size;
-  class->printer_list_papers = fallback_printer_list_papers;
-  class->printer_get_default_page_size = fallback_printer_get_default_page_size;
-  class->printer_get_capabilities = fallback_printer_get_capabilities;
-  class->request_password = request_password;
-  
-  g_object_class_install_property (object_class, 
-                                   PROP_STATUS,
-                                   g_param_spec_int ("status", NULL, NULL,
-                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
-                                                     GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
-                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
-                                                     GTK_PARAM_READWRITE)); 
-  
-  signals[PRINTER_LIST_CHANGED] =
-    g_signal_new (I_("printer-list-changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-  signals[PRINTER_LIST_DONE] =
-    g_signal_new (I_("printer-list-done"),
-                   G_TYPE_FROM_CLASS (class),
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
-                   NULL, NULL,
-                   NULL,
-                   G_TYPE_NONE, 0);
-  signals[PRINTER_ADDED] =
-    g_signal_new (I_("printer-added"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
-  signals[PRINTER_REMOVED] =
-    g_signal_new (I_("printer-removed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
-  signals[PRINTER_STATUS_CHANGED] =
-    g_signal_new (I_("printer-status-changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
-  signals[REQUEST_PASSWORD] =
-    g_signal_new (I_("request-password"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
-                 NULL, NULL, NULL,
-                 G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
-                 G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
-}
-
-static void
-gtk_print_backend_init (GtkPrintBackend *backend)
-{
-  GtkPrintBackendPrivate *priv;
-
-  priv = backend->priv = gtk_print_backend_get_instance_private (backend);
-
-  priv->printers = g_list_store_new (GTK_TYPE_PRINTER);
-  priv->auth_info_required = NULL;
-  priv->auth_info = NULL;
-}
-
-static void
-gtk_print_backend_dispose (GObject *object)
-{
-  GtkPrintBackend *backend;
-  GtkPrintBackendPrivate *priv;
-
-  backend = GTK_PRINT_BACKEND (object);
-  priv = backend->priv;
-
-  /* We unref the printers in dispose, not in finalize so that
-   * we can break refcount cycles with gtk_print_backend_destroy 
-   */
-  g_list_store_remove_all (priv->printers);
-
-  backend_parent_class->dispose (object);
-}
-
-static void
-gtk_print_backend_finalize (GObject *object)
-{
-  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
-  GtkPrintBackendPrivate *priv = backend->priv;
-
-  g_clear_object (&priv->printers);
-
-  backend_parent_class->finalize (object);
-}
-
-static void
-fallback_printer_request_details (GtkPrinter *printer)
-{
-}
-
-static gboolean
-fallback_printer_mark_conflicts (GtkPrinter          *printer,
-                                 GtkPrinterOptionSet *options)
-{
-  return FALSE;
-}
-
-static gboolean
-fallback_printer_get_hard_margins (GtkPrinter *printer,
-                                  double     *top,
-                                  double     *bottom,
-                                  double     *left,
-                                  double     *right)
-{
-  return FALSE;
-}
-
-static gboolean
-fallback_printer_get_hard_margins_for_paper_size (GtkPrinter   *printer,
-                                                 GtkPaperSize *paper_size,
-                                                 double       *top,
-                                                 double       *bottom,
-                                                 double       *left,
-                                                 double       *right)
-{
-  return FALSE;
-}
-
-static GList *
-fallback_printer_list_papers (GtkPrinter *printer)
-{
-  return NULL;
-}
-
-static GtkPageSetup *
-fallback_printer_get_default_page_size (GtkPrinter *printer)
-{
-  return NULL;
-}
-
-static GtkPrintCapabilities
-fallback_printer_get_capabilities (GtkPrinter *printer)
-{
-  return 0;
-}
-
-void
-gtk_print_backend_add_printer (GtkPrintBackend *backend,
-                              GtkPrinter      *printer)
-{
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
-  g_list_store_append (backend->priv->printers, printer);
-}
-
-void
-gtk_print_backend_remove_printer (GtkPrintBackend *backend,
-                                 GtkPrinter      *printer)
-{
-  guint position;
-  
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
-  if (g_list_store_find (backend->priv->printers, printer, &position))
-    g_list_store_remove (backend->priv->printers, position);
-}
-
-void
-gtk_print_backend_set_list_done (GtkPrintBackend *backend)
-{
-  if (!backend->priv->printer_list_done)
-    {
-      backend->priv->printer_list_done = TRUE;
-      g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
-    }
-}
-
-
-/**
- * gtk_print_backend_get_printer_list:
- *
- * Returns the current list of printers.
- *
- * Returns: (element-type GtkPrinter) (transfer container):
- *   A list of `GtkPrinter` objects
- */
-GList *
-gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
-{
-  GList *result = NULL;
-  guint i;
-  
-  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
-
-  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
-    {
-      GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
-      result = g_list_prepend (result, printer);
-      g_object_unref (printer);
-    }
-
-  if (!backend->priv->printer_list_requested)
-    {
-      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
-       GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
-      backend->priv->printer_list_requested = TRUE;
-    }
-
-  return result;
-}
-
-GListModel *
-gtk_print_backend_get_printers (GtkPrintBackend *backend)
-{
-  if (!backend->priv->printer_list_requested)
-    {
-      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
-       GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
-      backend->priv->printer_list_requested = TRUE;
-    }
-
-  return G_LIST_MODEL (backend->priv->printers);
-}
-
-gboolean
-gtk_print_backend_printer_list_is_done (GtkPrintBackend *backend)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), TRUE);
-
-  return backend->priv->printer_list_done;
-}
-
-GtkPrinter *
-gtk_print_backend_find_printer (GtkPrintBackend *backend,
-                                const char      *printer_name)
-{
-  GtkPrinter *result = NULL;
-  guint i;
-  
-  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
-
-  for (i = 0; !result && i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
-    {
-      GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
-      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
-        result = printer;
-      g_object_unref (printer);
-    }
-
-  return result;  
-}
-
-void
-gtk_print_backend_print_stream (GtkPrintBackend        *backend,
-                                GtkPrintJob            *job,
-                                GIOChannel             *data_io,
-                                GtkPrintJobCompleteFunc callback,
-                                gpointer                user_data,
-                               GDestroyNotify          dnotify)
-{
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
-  GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
-                                                      job,
-                                                      data_io,
-                                                      callback,
-                                                      user_data,
-                                                      dnotify);
-}
-
-void 
-gtk_print_backend_set_password (GtkPrintBackend  *backend,
-                                char            **auth_info_required,
-                                char            **auth_info,
-                                gboolean          store_auth_info)
-{
-  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
-
-  if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
-    GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
-                                                         auth_info_required,
-                                                         auth_info,
-                                                         store_auth_info);
-}
-
-static void
-store_auth_info_toggled (GtkCheckButton *chkbtn,
-                         gpointer        user_data)
-{
-  gboolean *data = (gboolean *) user_data;
-  *data = gtk_check_button_get_active (GTK_CHECK_BUTTON (chkbtn));
-}
-
-static void
-store_entry (GtkEntry  *entry,
-             gpointer   user_data)
-{
-  char **data = (char **) user_data;
-
-  if (*data != NULL)
-    {
-      memset (*data, 0, strlen (*data));
-      g_free (*data);
-    }
-
-  *data = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
-}
-
-static void
-password_dialog_response (GtkWidget       *dialog,
-                          int              response_id,
-                          GtkPrintBackend *backend)
-{
-  GtkPrintBackendPrivate *priv = backend->priv;
-  int i, auth_info_len;
-
-  if (response_id == GTK_RESPONSE_OK)
-    gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
-  else
-    gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
-
-  /* We want to clear the data before freeing it */
-  auth_info_len = g_strv_length (priv->auth_info_required);
-  for (i = 0; i < auth_info_len; i++)
-    {
-      if (priv->auth_info[i] != NULL)
-        {
-          memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
-          g_free (priv->auth_info[i]);
-          priv->auth_info[i] = NULL;
-        }
-    }
-
-  g_clear_pointer (&priv->auth_info, g_free);
-  g_clear_pointer (&priv->auth_info_required, g_strfreev);
-
-  gtk_window_destroy (GTK_WINDOW (dialog));
-
-  g_object_unref (backend);
-}
-
-static void
-request_password (GtkPrintBackend  *backend,
-                  gpointer          auth_info_required,
-                  gpointer          auth_info_default,
-                  gpointer          auth_info_display,
-                  gpointer          auth_info_visible,
-                  const char       *prompt,
-                  gboolean          can_store_auth_info)
-{
-  GtkPrintBackendPrivate *priv = backend->priv;
-  GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
-  GtkWidget *focus = NULL;
-  GtkWidget *content_area;
-  char      *markup;
-  int        length;
-  int        i;
-  char     **ai_required = (char **) auth_info_required;
-  char     **ai_default = (char **) auth_info_default;
-  char     **ai_display = (char **) auth_info_display;
-  gboolean  *ai_visible = (gboolean *) auth_info_visible;
-
-  priv->auth_info_required = g_strdupv (ai_required);
-  length = g_strv_length (ai_required);
-  priv->auth_info = g_new0 (char *, length + 1);
-  priv->store_auth_info = FALSE;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, 
-                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                         _("_OK"), GTK_RESPONSE_OK,
-                                         NULL);
-
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-  main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
-  /* Left */
-  icon = gtk_image_new_from_icon_name ("dialog-password-symbolic");
-  gtk_image_set_icon_size (GTK_IMAGE (icon), GTK_ICON_SIZE_LARGE);
-  gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
-  gtk_widget_set_valign (icon, GTK_ALIGN_START);
-  gtk_widget_set_margin_start (icon, 12);
-  gtk_widget_set_margin_end (icon, 12);
-  gtk_widget_set_margin_top (icon, 12);
-  gtk_widget_set_margin_bottom (icon, 12);
-
-  /* Right */
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-  gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
-
-  /* Right - 1. */
-  label = gtk_label_new (NULL);
-  markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
-  gtk_label_set_markup (GTK_LABEL (label), markup);
-  gtk_label_set_wrap (GTK_LABEL (label), TRUE);
-  gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
-  g_free (markup);
-
-  /* Packing */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-G_GNUC_END_IGNORE_DEPRECATIONS
-  gtk_box_append (GTK_BOX (content_area), main_box);
-
-  gtk_box_append (GTK_BOX (main_box), icon);
-  gtk_box_append (GTK_BOX (main_box), vbox);
-
-  gtk_box_append (GTK_BOX (vbox), label);
-
-  /* Right - 2. */
-  for (i = 0; i < length; i++)
-    {
-      priv->auth_info[i] = g_strdup (ai_default[i]);
-      if (ai_display[i] != NULL)
-        {
-          box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-          gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
-          gtk_widget_set_margin_top (box, 6);
-          gtk_widget_set_margin_bottom (box, 6);
-
-          label = gtk_label_new (ai_display[i]);
-          gtk_widget_set_halign (label, GTK_ALIGN_START);
-          gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
-
-          entry = gtk_entry_new ();
-          focus = entry;
-
-          if (ai_default[i] != NULL)
-            gtk_editable_set_text (GTK_EDITABLE (entry), ai_default[i]);
-
-          gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
-          gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
-
-          gtk_box_append (GTK_BOX (vbox), box);
-
-          gtk_box_append (GTK_BOX (box), label);
-          gtk_box_append (GTK_BOX (box), entry);
-
-          g_signal_connect (entry, "changed",
-                            G_CALLBACK (store_entry), &(priv->auth_info[i]));
-        }
-    }
-
-  if (can_store_auth_info)
-    {
-      chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
-      gtk_widget_set_margin_top (chkbtn, 6);
-      gtk_widget_set_margin_bottom (chkbtn, 6);
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (chkbtn), FALSE);
-      gtk_box_append (GTK_BOX (vbox), chkbtn);
-      g_signal_connect (chkbtn, "toggled",
-                        G_CALLBACK (store_auth_info_toggled),
-                        &(priv->store_auth_info));
-    }
-
-  if (focus != NULL)
-    {
-      gtk_widget_grab_focus (focus);
-      focus = NULL;
-    }
-
-  g_object_ref (backend);
-  g_signal_connect (G_OBJECT (dialog), "response",
-                    G_CALLBACK (password_dialog_response), backend);
-
-  gtk_window_present (GTK_WINDOW (dialog));
-}
-
-void
-gtk_print_backend_destroy (GtkPrintBackend *backend)
-{
-  /* The lifecycle of print backends and printers are tied, such that
-   * the backend owns the printers, but the printers also ref the backend.
-   * This is so that if the app has a reference to a printer its backend
-   * will be around. However, this results in a cycle, which we break
-   * with this call, which causes the print backend to release its printers.
-   */
-  g_object_run_dispose (G_OBJECT (backend));
-}
diff --git a/gtk/gtkprintbackendprivate.h b/gtk/gtkprintbackendprivate.h
deleted file mode 100644 (file)
index be14331..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinteroptionsetprivate.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GtkPrintBackendClass    GtkPrintBackendClass;
-typedef struct _GtkPrintBackendPrivate  GtkPrintBackendPrivate;
-
-#define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
-
-typedef enum
-{
-  /* TODO: add specific errors */
-  GTK_PRINT_BACKEND_ERROR_GENERIC
-} GtkPrintBackendError;
-
-GDK_AVAILABLE_IN_ALL
-GQuark     gtk_print_backend_error_quark      (void);
-
-#define GTK_TYPE_PRINT_BACKEND                  (gtk_print_backend_get_type ())
-#define GTK_PRINT_BACKEND(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
-#define GTK_PRINT_BACKEND_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
-#define GTK_IS_PRINT_BACKEND(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
-#define GTK_IS_PRINT_BACKEND_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
-#define GTK_PRINT_BACKEND_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
-
-typedef enum 
-{
-  GTK_PRINT_BACKEND_STATUS_UNKNOWN,
-  GTK_PRINT_BACKEND_STATUS_OK,
-  GTK_PRINT_BACKEND_STATUS_UNAVAILABLE
-} GtkPrintBackendStatus;
-
-struct _GtkPrintBackend
-{
-  GObject parent_instance;
-
-  GtkPrintBackendPrivate *priv;
-};
-
-struct _GtkPrintBackendClass
-{
-  GObjectClass parent_class;
-
-  /* Global backend methods: */
-  void                   (*request_printer_list)            (GtkPrintBackend        *backend);
-  void                   (*print_stream)                    (GtkPrintBackend        *backend,
-                                                            GtkPrintJob            *job,
-                                                            GIOChannel             *data_io,
-                                                            GtkPrintJobCompleteFunc callback,
-                                                            gpointer                user_data,
-                                                            GDestroyNotify          dnotify);
-
-  /* Printer methods: */
-  void                  (*printer_request_details)           (GtkPrinter          *printer);
-  cairo_surface_t *     (*printer_create_cairo_surface)      (GtkPrinter          *printer,
-                                                             GtkPrintSettings    *settings,
-                                                             double               height,
-                                                             double               width,
-                                                             GIOChannel          *cache_io);
-  GtkPrinterOptionSet * (*printer_get_options)               (GtkPrinter          *printer,
-                                                             GtkPrintSettings    *settings,
-                                                             GtkPageSetup        *page_setup,
-                                                             GtkPrintCapabilities capabilities);
-  gboolean              (*printer_mark_conflicts)            (GtkPrinter          *printer,
-                                                             GtkPrinterOptionSet *options);
-  void                  (*printer_get_settings_from_options) (GtkPrinter          *printer,
-                                                             GtkPrinterOptionSet *options,
-                                                             GtkPrintSettings    *settings);
-  void                  (*printer_prepare_for_print)         (GtkPrinter          *printer,
-                                                             GtkPrintJob         *print_job,
-                                                             GtkPrintSettings    *settings,
-                                                             GtkPageSetup        *page_setup);
-  GList  *              (*printer_list_papers)               (GtkPrinter          *printer);
-  GtkPageSetup *        (*printer_get_default_page_size)     (GtkPrinter          *printer);
-  gboolean              (*printer_get_hard_margins)          (GtkPrinter          *printer,
-                                                             double              *top,
-                                                             double              *bottom,
-                                                             double              *left,
-                                                             double              *right);
-  GtkPrintCapabilities  (*printer_get_capabilities)          (GtkPrinter          *printer);
-
-  /* Signals */
-  void                  (*printer_list_changed)              (GtkPrintBackend     *backend);
-  void                  (*printer_list_done)                 (GtkPrintBackend     *backend);
-  void                  (*printer_added)                     (GtkPrintBackend     *backend,
-                                                             GtkPrinter          *printer);
-  void                  (*printer_removed)                   (GtkPrintBackend     *backend,
-                                                             GtkPrinter          *printer);
-  void                  (*printer_status_changed)            (GtkPrintBackend     *backend,
-                                                             GtkPrinter          *printer);
-  void                  (*request_password)                  (GtkPrintBackend     *backend,
-                                                              gpointer             auth_info_required,
-                                                              gpointer             auth_info_default,
-                                                              gpointer             auth_info_display,
-                                                              gpointer             auth_info_visible,
-                                                              const char          *prompt,
-                                                              gboolean             can_store_auth_info);
-
-  /* not a signal */
-  void                  (*set_password)                      (GtkPrintBackend     *backend,
-                                                              char               **auth_info_required,
-                                                              char               **auth_info,
-                                                              gboolean             store_auth_info);
-
-  gboolean              (*printer_get_hard_margins_for_paper_size) (GtkPrinter    *printer,
-                                                                   GtkPaperSize  *paper_size,
-                                                                   double        *top,
-                                                                   double        *bottom,
-                                                                   double        *left,
-                                                                   double        *right);
-};
-
-#define GTK_PRINT_BACKEND_EXTENSION_POINT_NAME "gtk-print-backend"
-
-GDK_AVAILABLE_IN_ALL
-GType   gtk_print_backend_get_type       (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GList      *gtk_print_backend_get_printer_list     (GtkPrintBackend         *print_backend);
-GDK_AVAILABLE_IN_ALL
-GListModel *gtk_print_backend_get_printers         (GtkPrintBackend         *print_backend);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_print_backend_printer_list_is_done (GtkPrintBackend         *print_backend);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter *gtk_print_backend_find_printer         (GtkPrintBackend         *print_backend,
-                                                   const char              *printer_name);
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_print_stream         (GtkPrintBackend         *print_backend,
-                                                   GtkPrintJob             *job,
-                                                   GIOChannel              *data_io,
-                                                   GtkPrintJobCompleteFunc  callback,
-                                                   gpointer                 user_data,
-                                                   GDestroyNotify           dnotify);
-GDK_AVAILABLE_IN_ALL
-GList *     gtk_print_backend_load_modules         (void);
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_destroy              (GtkPrintBackend         *print_backend);
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_set_password         (GtkPrintBackend         *backend, 
-                                                    char                   **auth_info_required,
-                                                    char                   **auth_info,
-                                                    gboolean                 can_store_auth_info);
-
-/* Backend-only functions for GtkPrintBackend */
-
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_add_printer          (GtkPrintBackend         *print_backend,
-                                                   GtkPrinter              *printer);
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_remove_printer       (GtkPrintBackend         *print_backend,
-                                                   GtkPrinter              *printer);
-GDK_AVAILABLE_IN_ALL
-void        gtk_print_backend_set_list_done        (GtkPrintBackend         *backend);
-
-
-/* Backend-only functions for GtkPrinter */
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_is_new                (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_accepts_pdf       (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_accepts_ps        (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_is_new            (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_is_active         (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_is_paused         (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_is_accepting_jobs (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_has_details       (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_is_default        (GtkPrinter      *printer,
-                                              gboolean         val);
-GDK_AVAILABLE_IN_ALL
-void        gtk_printer_set_icon_name         (GtkPrinter      *printer,
-                                              const char      *icon);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_job_count         (GtkPrinter      *printer,
-                                              int              count);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_location          (GtkPrinter      *printer,
-                                              const char      *location);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_description       (GtkPrinter      *printer,
-                                              const char      *description);
-GDK_AVAILABLE_IN_ALL
-gboolean    gtk_printer_set_state_message     (GtkPrinter      *printer,
-                                              const char      *message);
-
-void        gtk_print_backends_init (void);
-
-
-G_END_DECLS
-
diff --git a/gtk/gtkprinter.c b/gtk/gtkprinter.c
deleted file mode 100644 (file)
index 9b16d02..0000000
+++ /dev/null
@@ -1,1368 +0,0 @@
-/* GtkPrinter
- * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "gtkprivate.h"
-
-#include "gtkprinter.h"
-#include "gtkprinterprivate.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprintjob.h"
-
-/**
- * GtkPrinter:
- *
- * A `GtkPrinter` object represents a printer.
- *
- * You only need to deal directly with printers if you use the
- * non-portable [class@Gtk.PrintUnixDialog] API.
- *
- * A `GtkPrinter` allows to get status information about the printer,
- * such as its description, its location, the number of queued jobs,
- * etc. Most importantly, a `GtkPrinter` object can be used to create
- * a [class@Gtk.PrintJob] object, which lets you print to the printer.
- */
-
-
-static void gtk_printer_finalize     (GObject *object);
-
-struct _GtkPrinterPrivate
-{
-  char *name;
-  char *location;
-  char *description;
-  char *icon_name;
-
-  guint is_active         : 1;
-  guint is_paused         : 1;
-  guint is_accepting_jobs : 1;
-  guint is_new            : 1;
-  guint is_virtual        : 1;
-  guint is_default        : 1;
-  guint has_details       : 1;
-  guint accepts_pdf       : 1;
-  guint accepts_ps        : 1;
-
-  char *state_message;
-  int job_count;
-
-  GtkPrintBackend *backend;
-};
-
-enum {
-  DETAILS_ACQUIRED,
-  LAST_SIGNAL
-};
-
-enum {
-  PROP_0,
-  PROP_NAME,
-  PROP_BACKEND,
-  PROP_IS_VIRTUAL,
-  PROP_STATE_MESSAGE,
-  PROP_LOCATION,
-  PROP_ICON_NAME,
-  PROP_JOB_COUNT,
-  PROP_ACCEPTS_PDF,
-  PROP_ACCEPTS_PS,
-  PROP_PAUSED,
-  PROP_ACCEPTING_JOBS
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void gtk_printer_set_property (GObject      *object,
-                                     guint         prop_id,
-                                     const GValue *value,
-                                     GParamSpec   *pspec);
-static void gtk_printer_get_property (GObject      *object,
-                                     guint         prop_id,
-                                     GValue       *value,
-                                     GParamSpec   *pspec);
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinter, gtk_printer, G_TYPE_OBJECT)
-
-static void
-gtk_printer_class_init (GtkPrinterClass *class)
-{
-  GObjectClass *object_class;
-  object_class = (GObjectClass *) class;
-
-  object_class->finalize = gtk_printer_finalize;
-
-  object_class->set_property = gtk_printer_set_property;
-  object_class->get_property = gtk_printer_get_property;
-
-  /**
-   * GtkPrinter:name: (attributes org.gtk.Property.get=gtk_printer_get_name)
-   *
-   * The name of the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_NAME,
-                                   g_param_spec_string ("name", NULL, NULL,
-                                                       "",
-                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrinter:backend: (attributes org.gtk.Property.get=gtk_printer_get_backend)
-   *
-   * The backend for the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_BACKEND,
-                                   g_param_spec_object ("backend", NULL, NULL,
-                                                       GTK_TYPE_PRINT_BACKEND,
-                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrinter:is-virtual: (attributes org.gtk.Property.get=gtk_printer_is_virtual)
-   *
-   * %FALSE if this represents a real hardware device.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_IS_VIRTUAL,
-                                   g_param_spec_boolean ("is-virtual", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrinter:accepts-pdf: (attributes org.gtk.Property.get=gtk_printer_accepts_pdf)
-   *
-   * %TRUE if this printer can accept PDF.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_ACCEPTS_PDF,
-                                   g_param_spec_boolean ("accepts-pdf", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrinter:accepts-ps: (attributes org.gtk.Property.get=gtk_printer_accepts_ps)
-   *
-   * %TRUE if this printer can accept PostScript.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_ACCEPTS_PS,
-                                   g_param_spec_boolean ("accepts-ps", NULL, NULL,
-                                                        TRUE,
-                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrinter:state-message: (attributes org.gtk.Property.get=gtk_printer_get_state_message)
-   *
-   * String giving the current status of the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_STATE_MESSAGE,
-                                   g_param_spec_string ("state-message", NULL, NULL,
-                                                       "",
-                                                       GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter:location: (attributes org.gtk.Property.get=gtk_printer_get_location)
-   *
-   * Information about the location of the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_LOCATION,
-                                   g_param_spec_string ("location", NULL, NULL,
-                                                       "",
-                                                       GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter:icon-name: (attributes org.gtk.Property.get=gtk_printer_get_icon_name)
-   *
-   * Icon name to use for the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_ICON_NAME,
-                                   g_param_spec_string ("icon-name", NULL, NULL,
-                                                       "printer",
-                                                       GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter:job-count: (attributes org.gtk.Property.get=gtk_printer_get_job_count)
-   *
-   * Number of jobs queued in the printer.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_JOB_COUNT,
-                                  g_param_spec_int ("job-count", NULL, NULL,
-                                                    0,
-                                                    G_MAXINT,
-                                                    0,
-                                                    GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter:paused: (attributes org.gtk.Property.get=gtk_printer_is_paused)
-   *
-   * %TRUE if this printer is paused.
-   *
-   * A paused printer still accepts jobs, but it does
-   * not print them.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_PAUSED,
-                                   g_param_spec_boolean ("paused", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter:accepting-jobs: (attributes org.gtk.Property.get=gtk_printer_is_accepting_jobs)
-   *
-   * %TRUE if the printer is accepting jobs.
-   */
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_ACCEPTING_JOBS,
-                                   g_param_spec_boolean ("accepting-jobs", NULL, NULL,
-                                                        TRUE,
-                                                        GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrinter::details-acquired:
-   * @printer: the `GtkPrinter` on which the signal is emitted
-   * @success: %TRUE if the details were successfully acquired
-   *
-   * Emitted in response to a request for detailed information
-   * about a printer from the print backend.
-   *
-   * The @success parameter indicates if the information was
-   * actually obtained.
-   */
-  signals[DETAILS_ACQUIRED] =
-    g_signal_new (I_("details-acquired"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrinterClass, details_acquired),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-}
-
-static void
-gtk_printer_init (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  priv->name = NULL;
-  priv->location = NULL;
-  priv->description = NULL;
-  priv->icon_name = g_strdup ("printer");
-
-  priv->is_active = TRUE;
-  priv->is_paused = FALSE;
-  priv->is_accepting_jobs = TRUE;
-  priv->is_new = TRUE;
-  priv->has_details = FALSE;
-  priv->accepts_pdf = FALSE;
-  priv->accepts_ps = TRUE;
-
-  priv->state_message = NULL;  
-  priv->job_count = 0;
-}
-
-static void
-gtk_printer_finalize (GObject *object)
-{
-  GtkPrinter *printer = GTK_PRINTER (object);
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_free (priv->name);
-  g_free (priv->location);
-  g_free (priv->description);
-  g_free (priv->state_message);
-  g_free (priv->icon_name);
-
-  if (priv->backend)
-    g_object_unref (priv->backend);
-
-  G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_set_property (GObject         *object,
-                         guint            prop_id,
-                         const GValue    *value,
-                         GParamSpec      *pspec)
-{
-  GtkPrinter *printer = GTK_PRINTER (object);
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  switch (prop_id)
-    {
-    case PROP_NAME:
-      priv->name = g_value_dup_string (value);
-      break;
-    
-    case PROP_BACKEND:
-      priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
-      break;
-
-    case PROP_IS_VIRTUAL:
-      priv->is_virtual = g_value_get_boolean (value);
-      break;
-
-    case PROP_ACCEPTS_PDF:
-      priv->accepts_pdf = g_value_get_boolean (value);
-      break;
-
-    case PROP_ACCEPTS_PS:
-      priv->accepts_ps = g_value_get_boolean (value);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_printer_get_property (GObject    *object,
-                         guint       prop_id,
-                         GValue     *value,
-                         GParamSpec *pspec)
-{
-  GtkPrinter *printer = GTK_PRINTER (object);
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  switch (prop_id)
-    {
-    case PROP_NAME:
-      if (priv->name)
-       g_value_set_string (value, priv->name);
-      else
-       g_value_set_static_string (value, "");
-      break;
-    case PROP_BACKEND:
-      g_value_set_object (value, priv->backend);
-      break;
-    case PROP_STATE_MESSAGE:
-      if (priv->state_message)
-       g_value_set_string (value, priv->state_message);
-      else
-       g_value_set_static_string (value, "");
-      break;
-    case PROP_LOCATION:
-      if (priv->location)
-       g_value_set_string (value, priv->location);
-      else
-       g_value_set_static_string (value, "");
-      break;
-    case PROP_ICON_NAME:
-      if (priv->icon_name)
-       g_value_set_string (value, priv->icon_name);
-      else
-       g_value_set_static_string (value, "printer");
-      break;
-    case PROP_JOB_COUNT:
-      g_value_set_int (value, priv->job_count);
-      break;
-    case PROP_IS_VIRTUAL:
-      g_value_set_boolean (value, priv->is_virtual);
-      break;
-    case PROP_ACCEPTS_PDF:
-      g_value_set_boolean (value, priv->accepts_pdf);
-      break;
-    case PROP_ACCEPTS_PS:
-      g_value_set_boolean (value, priv->accepts_ps);
-      break;
-    case PROP_PAUSED:
-      g_value_set_boolean (value, priv->is_paused);
-      break;
-    case PROP_ACCEPTING_JOBS:
-      g_value_set_boolean (value, priv->is_accepting_jobs);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-/**
- * gtk_printer_new:
- * @name: the name of the printer
- * @backend: a `GtkPrintBackend`
- * @virtual_: whether the printer is virtual
- *
- * Creates a new `GtkPrinter`.
- *
- * Returns: a new `GtkPrinter`
- */
-GtkPrinter *
-gtk_printer_new (const char      *name,
-                GtkPrintBackend *backend,
-                gboolean         virtual_)
-{
-  GObject *result;
-  
-  result = g_object_new (GTK_TYPE_PRINTER,
-                        "name", name,
-                        "backend", backend,
-                        "is-virtual", virtual_,
-                         NULL);
-
-  return (GtkPrinter *) result;
-}
-
-/**
- * gtk_printer_get_backend: (attributes org.gtk.Method.get_property=backend)
- * @printer: a `GtkPrinter`
- *
- * Returns the backend of the printer.
- *
- * Returns: (transfer none): the backend of @printer
- */
-GtkPrintBackend *
-gtk_printer_get_backend (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-  
-  return priv->backend;
-}
-
-/**
- * gtk_printer_get_name: (attributes org.gtk.Method.get_property=name)
- * @printer: a `GtkPrinter`
- *
- * Returns the name of the printer.
- *
- * Returns: the name of @printer
- */
-const char *
-gtk_printer_get_name (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  return priv->name;
-}
-
-/**
- * gtk_printer_get_description:
- * @printer: a `GtkPrinter`
- *
- * Gets the description of the printer.
- *
- * Returns: the description of @printer
- */
-const char *
-gtk_printer_get_description (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-  
-  return priv->description;
-}
-
-gboolean
-gtk_printer_set_description (GtkPrinter  *printer,
-                            const char *description)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (g_strcmp0 (priv->description, description) == 0)
-    return FALSE;
-
-  g_free (priv->description);
-  priv->description = g_strdup (description);
-  
-  return TRUE;
-}
-
-/**
- * gtk_printer_get_state_message: (attributes org.gtk.Method.get_property=state-message)
- * @printer: a `GtkPrinter`
- *
- * Returns the state message describing the current state
- * of the printer.
- *
- * Returns: the state message of @printer
- */
-const char *
-gtk_printer_get_state_message (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  return priv->state_message;
-}
-
-gboolean
-gtk_printer_set_state_message (GtkPrinter  *printer,
-                              const char *message)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (g_strcmp0 (priv->state_message, message) == 0)
-    return FALSE;
-
-  g_free (priv->state_message);
-  priv->state_message = g_strdup (message);
-  g_object_notify (G_OBJECT (printer), "state-message");
-
-  return TRUE;
-}
-
-/**
- * gtk_printer_get_location: (attributes org.gtk.Method.get_property=location)
- * @printer: a `GtkPrinter`
- *
- * Returns a description of the location of the printer.
- *
- * Returns: the location of @printer
- */
-const char *
-gtk_printer_get_location (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  return priv->location;
-}
-
-gboolean
-gtk_printer_set_location (GtkPrinter  *printer,
-                         const char *location)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (g_strcmp0 (priv->location, location) == 0)
-    return FALSE;
-
-  g_free (priv->location);
-  priv->location = g_strdup (location);
-  g_object_notify (G_OBJECT (printer), "location");
-  
-  return TRUE;
-}
-
-/**
- * gtk_printer_get_icon_name: (attributes org.gtk.Method.get_property=icon-name)
- * @printer: a `GtkPrinter`
- *
- * Gets the name of the icon to use for the printer.
- *
- * Returns: the icon name for @printer
- */
-const char *
-gtk_printer_get_icon_name (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  return priv->icon_name;
-}
-
-void
-gtk_printer_set_icon_name (GtkPrinter  *printer,
-                          const char *icon)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  g_free (priv->icon_name);
-  priv->icon_name = g_strdup (icon);
-  g_object_notify (G_OBJECT (printer), "icon-name");
-}
-
-/**
- * gtk_printer_get_job_count: (attributes org.gtk.Method.get_property=job-count)
- * @printer: a `GtkPrinter`
- *
- * Gets the number of jobs currently queued on the printer.
- *
- * Returns: the number of jobs on @printer
- */
-int
-gtk_printer_get_job_count (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
-
-  return priv->job_count;
-}
-
-gboolean
-gtk_printer_set_job_count (GtkPrinter *printer,
-                          int         count)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (priv->job_count == count)
-    return FALSE;
-
-  priv->job_count = count;
-  
-  g_object_notify (G_OBJECT (printer), "job-count");
-  
-  return TRUE;
-}
-
-/**
- * gtk_printer_has_details:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer details are available.
- *
- * Returns: %TRUE if @printer details are available
- */
-gboolean
-gtk_printer_has_details (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  return priv->has_details;
-}
-
-void
-gtk_printer_set_has_details (GtkPrinter *printer,
-                            gboolean    val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  priv->has_details = val;
-}
-
-/**
- * gtk_printer_is_active:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is currently active (i.e.
- * accepts new jobs).
- *
- * Returns: %TRUE if @printer is active
- */
-gboolean
-gtk_printer_is_active (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->is_active;
-}
-
-void
-gtk_printer_set_is_active (GtkPrinter *printer,
-                          gboolean val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  priv->is_active = val;
-}
-
-/**
- * gtk_printer_is_paused: (attributes org.gtk.Method.get_property=paused)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is currently paused.
- *
- * A paused printer still accepts jobs, but it is not
- * printing them.
- *
- * Returns: %TRUE if @printer is paused
- */
-gboolean
-gtk_printer_is_paused (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->is_paused;
-}
-
-gboolean
-gtk_printer_set_is_paused (GtkPrinter *printer,
-                          gboolean    val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (val == priv->is_paused)
-    return FALSE;
-
-  priv->is_paused = val;
-
-  return TRUE;
-}
-
-/**
- * gtk_printer_is_accepting_jobs: (attributes org.gtk.Method.get_property=accepting-jobs)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is accepting jobs
- *
- * Returns: %TRUE if @printer is accepting jobs
- */
-gboolean
-gtk_printer_is_accepting_jobs (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->is_accepting_jobs;
-}
-
-gboolean
-gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
-                                  gboolean val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-
-  if (val == priv->is_accepting_jobs)
-    return FALSE;
-
-  priv->is_accepting_jobs = val;
-
-  return TRUE;
-}
-
-/**
- * gtk_printer_is_virtual: (attributes org.gtk.Method.get_property=is-virtual)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is virtual (i.e. does not
- * represent actual printer hardware, but something like
- * a CUPS class).
- *
- * Returns: %TRUE if @printer is virtual
- */
-gboolean
-gtk_printer_is_virtual (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->is_virtual;
-}
-
-/**
- * gtk_printer_accepts_pdf: (attributes org.gtk.Method.get_property=accepts-pdf)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer accepts input in
- * PDF format.
- *
- * Returns: %TRUE if @printer accepts PDF
- */
-gboolean
-gtk_printer_accepts_pdf (GtkPrinter *printer)
-{ 
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->accepts_pdf;
-}
-
-void
-gtk_printer_set_accepts_pdf (GtkPrinter *printer,
-                            gboolean val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  priv->accepts_pdf = val;
-}
-
-/**
- * gtk_printer_accepts_ps: (attributes org.gtk.Method.get_property=accepts-ps)
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer accepts input in
- * PostScript format.
- *
- * Returns: %TRUE if @printer accepts PostScript
- */
-gboolean
-gtk_printer_accepts_ps (GtkPrinter *printer)
-{ 
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
-  
-  return priv->accepts_ps;
-}
-
-void
-gtk_printer_set_accepts_ps (GtkPrinter *printer,
-                           gboolean val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  priv->accepts_ps = val;
-}
-
-gboolean
-gtk_printer_is_new (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-  
-  return priv->is_new;
-}
-
-void
-gtk_printer_set_is_new (GtkPrinter *printer,
-                       gboolean val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  priv->is_new = val;
-}
-
-
-/**
- * gtk_printer_is_default:
- * @printer: a `GtkPrinter`
- *
- * Returns whether the printer is the default printer.
- *
- * Returns: %TRUE if @printer is the default
- */
-gboolean
-gtk_printer_is_default (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
-  
-  return priv->is_default;
-}
-
-void
-gtk_printer_set_is_default (GtkPrinter *printer,
-                           gboolean    val)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  priv->is_default = val;
-}
-
-/**
- * gtk_printer_request_details:
- * @printer: a `GtkPrinter`
- *
- * Requests the printer details.
- *
- * When the details are available, the
- * [signal@Gtk.Printer::details-acquired] signal
- * will be emitted on @printer.
- */
-void
-gtk_printer_request_details (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class;
-
-  g_return_if_fail (GTK_IS_PRINTER (printer));
-
-  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-  backend_class->printer_request_details (printer);
-}
-
-GtkPrinterOptionSet *
-_gtk_printer_get_options (GtkPrinter           *printer,
-                         GtkPrintSettings     *settings,
-                         GtkPageSetup         *page_setup,
-                         GtkPrintCapabilities  capabilities)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_get_options (printer, settings, page_setup, capabilities);
-}
-
-gboolean
-_gtk_printer_mark_conflicts (GtkPrinter          *printer,
-                            GtkPrinterOptionSet *options)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_mark_conflicts (printer, options);
-}
-  
-void
-_gtk_printer_get_settings_from_options (GtkPrinter          *printer,
-                                       GtkPrinterOptionSet *options,
-                                       GtkPrintSettings    *settings)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  backend_class->printer_get_settings_from_options (printer, options, settings);
-}
-
-void
-_gtk_printer_prepare_for_print (GtkPrinter       *printer,
-                               GtkPrintJob      *print_job,
-                               GtkPrintSettings *settings,
-                               GtkPageSetup     *page_setup)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
-}
-
-cairo_surface_t *
-_gtk_printer_create_cairo_surface (GtkPrinter       *printer,
-                                  GtkPrintSettings *settings,
-                                  double            width, 
-                                  double            height,
-                                  GIOChannel       *cache_io)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_create_cairo_surface (printer, settings,
-                                                     width, height, cache_io);
-}
-
-/**
- * gtk_printer_list_papers:
- * @printer: a `GtkPrinter`
- *
- * Lists all the paper sizes @printer supports.
- *
- * This will return and empty list unless the printer’s details
- * are available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: (element-type GtkPageSetup) (transfer full): a newly
- *   allocated list of newly allocated `GtkPageSetup`s.
- */
-GList  *
-gtk_printer_list_papers (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class;
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-  return backend_class->printer_list_papers (printer);
-}
-
-/**
- * gtk_printer_get_default_page_size:
- * @printer: a `GtkPrinter`
- *
- * Returns default page size of @printer.
- *
- * Returns: (transfer full): a newly allocated `GtkPageSetup` with default page size
- *   of the printer.
- */
-GtkPageSetup *
-gtk_printer_get_default_page_size (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class;
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
-
-  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_get_default_page_size (printer);
-}
-
-/**
- * gtk_printer_get_hard_margins:
- * @printer: a `GtkPrinter`
- * @top: (out): a location to store the top margin in
- * @bottom: (out): a location to store the bottom margin in
- * @left: (out): a location to store the left margin in
- * @right: (out): a location to store the right margin in
- *
- * Retrieve the hard margins of @printer.
- *
- * These are the margins that define the area at the borders
- * of the paper that the printer cannot print to.
- *
- * Note: This will not succeed unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: %TRUE iff the hard margins were retrieved
- */
-gboolean
-gtk_printer_get_hard_margins (GtkPrinter *printer,
-                             double     *top,
-                             double     *bottom,
-                             double     *left,
-                             double     *right)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
-}
-
-/**
- * gtk_printer_get_hard_margins_for_paper_size:
- * @printer: a `GtkPrinter`
- * @paper_size: a `GtkPaperSize`
- * @top: (out): a location to store the top margin in
- * @bottom: (out): a location to store the bottom margin in
- * @left: (out): a location to store the left margin in
- * @right: (out): a location to store the right margin in
- *
- * Retrieve the hard margins of @printer for @paper_size.
- *
- * These are the margins that define the area at the borders
- * of the paper that the printer cannot print to.
- *
- * Note: This will not succeed unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Return value: %TRUE iff the hard margins were retrieved
- */
-gboolean
-gtk_printer_get_hard_margins_for_paper_size (GtkPrinter   *printer,
-                                            GtkPaperSize *paper_size,
-                                            double       *top,
-                                            double       *bottom,
-                                            double       *left,
-                                            double       *right)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-
-  return backend_class->printer_get_hard_margins_for_paper_size (printer, paper_size, top, bottom, left, right);
-}
-
-/**
- * gtk_printer_get_capabilities:
- * @printer: a `GtkPrinter`
- * 
- * Returns the printer’s capabilities.
- *
- * This is useful when you’re using `GtkPrintUnixDialog`’s
- * manual-capabilities setting and need to know which settings
- * the printer can handle and which you must handle yourself.
- *
- * This will return 0 unless the printer’s details are
- * available, see [method@Gtk.Printer.has_details] and
- * [method@Gtk.Printer.request_details].
- *
- * Returns: the printer’s capabilities
- */
-GtkPrintCapabilities
-gtk_printer_get_capabilities (GtkPrinter *printer)
-{
-  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
-  GtkPrintBackendClass *backend_class;
-
-  g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
-
-  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
-  return backend_class->printer_get_capabilities (printer);
-}
-
-/**
- * gtk_printer_compare:
- * @a: a `GtkPrinter`
- * @b: another `GtkPrinter`
- *
- * Compares two printers.
- *
- * Returns: 0 if the printer match, a negative value if @a < @b,
- *   or a positive value if @a > @b
- */
-int
-gtk_printer_compare (GtkPrinter *a, 
-                     GtkPrinter *b)
-{
-  const char *name_a, *name_b;
-  
-  g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
-  
-  name_a = gtk_printer_get_name (a);
-  name_b = gtk_printer_get_name (b);
-  if (name_a == NULL  && name_b == NULL)
-    return 0;
-  else if (name_a == NULL)
-    return G_MAXINT;
-  else if (name_b == NULL)
-    return G_MININT;
-  else
-    return g_ascii_strcasecmp (name_a, name_b);
-}
-
-
-typedef struct 
-{
-  GList *backends;
-  GtkPrinterFunc func;
-  gpointer data;
-  GDestroyNotify destroy;
-  GMainLoop *loop;
-} PrinterList;
-
-static void list_done_cb (GtkPrintBackend *backend, 
-                         PrinterList     *printer_list);
-
-static void
-stop_enumeration (PrinterList *printer_list)
-{
-  GList *list, *next;
-  GtkPrintBackend *backend;
-
-  for (list = printer_list->backends; list; list = next)
-    {
-      next = list->next;
-      backend = GTK_PRINT_BACKEND (list->data);
-      list_done_cb (backend, printer_list);
-    }
-}
-
-static void 
-free_printer_list (PrinterList *printer_list)
-{
-  if (printer_list->destroy)
-    printer_list->destroy (printer_list->data);
-
-  if (printer_list->loop)
-    {    
-      g_main_loop_quit (printer_list->loop);
-      g_main_loop_unref (printer_list->loop);
-    }
-
-  g_free (printer_list);
-}
-
-static gboolean
-list_added_cb (GtkPrintBackend *backend, 
-              GtkPrinter      *printer, 
-              PrinterList     *printer_list)
-{
-  if (printer_list->func (printer, printer_list->data))
-    {
-      stop_enumeration (printer_list);
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-backend_status_changed (GObject    *object,
-                        GParamSpec *pspec,
-                        gpointer    data)
-{
-  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
-  PrinterList *printer_list = data;
-  GtkPrintBackendStatus status;
-
-  g_object_get (backend, "status", &status, NULL);
-  if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE)
-    list_done_cb (backend, printer_list);  
-}
-
-static gboolean
-list_printers_remove_backend (PrinterList     *printer_list,
-                              GtkPrintBackend *backend)
-{
-  printer_list->backends = g_list_remove (printer_list->backends, backend);
-  gtk_print_backend_destroy (backend);
-  g_object_unref (backend);
-
-  if (printer_list->backends == NULL)
-    {
-      free_printer_list (printer_list);
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-list_done_cb (GtkPrintBackend *backend,
-             PrinterList     *printer_list)
-{
-  g_signal_handlers_disconnect_by_func (backend, list_added_cb, printer_list);
-  g_signal_handlers_disconnect_by_func (backend, list_done_cb, printer_list);
-  g_signal_handlers_disconnect_by_func (backend, backend_status_changed, printer_list);
-
-  list_printers_remove_backend(printer_list, backend);
-}
-
-static gboolean
-list_printers_init (PrinterList     *printer_list,
-                   GtkPrintBackend *backend)
-{
-  GList *list, *node;
-  GtkPrintBackendStatus status;
-
-  list = gtk_print_backend_get_printer_list (backend);
-
-  for (node = list; node != NULL; node = node->next)
-    {
-      if (list_added_cb (backend, node->data, printer_list))
-        {
-          g_list_free (list);
-          return TRUE;
-        }
-    }
-
-  g_list_free (list);
-
-  g_object_get (backend, "status", &status, NULL);
-  
-  if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE || 
-      gtk_print_backend_printer_list_is_done (backend))
-    {
-      if (list_printers_remove_backend (printer_list, backend))
-        return TRUE;
-    }
-  else
-    {
-      g_signal_connect (backend, "printer-added", 
-                       (GCallback) list_added_cb, 
-                       printer_list);
-      g_signal_connect (backend, "printer-list-done", 
-                       (GCallback) list_done_cb, 
-                       printer_list);
-      g_signal_connect (backend, "notify::status", 
-                        (GCallback) backend_status_changed,
-                        printer_list);     
-    }
-
-  return FALSE;
-}
-
-/**
- * gtk_enumerate_printers:
- * @func: a function to call for each printer
- * @data: user data to pass to @func
- * @destroy: function to call if @data is no longer needed
- * @wait: if %TRUE, wait in a recursive mainloop until
- *    all printers are enumerated; otherwise return early
- *
- * Calls a function for all `GtkPrinter`s.
- *
- * If @func returns %TRUE, the enumeration is stopped.
- */
-void
-gtk_enumerate_printers (GtkPrinterFunc func,
-                       gpointer       data,
-                       GDestroyNotify destroy,
-                       gboolean       wait)
-{
-  PrinterList *printer_list;
-  GList *node, *next;
-  GtkPrintBackend *backend;
-
-  printer_list = g_new0 (PrinterList, 1);
-
-  printer_list->func = func;
-  printer_list->data = data;
-  printer_list->destroy = destroy;
-
-  if (g_module_supported ())
-    printer_list->backends = gtk_print_backend_load_modules ();
-  
-  if (printer_list->backends == NULL)
-    {
-      free_printer_list (printer_list);
-      return;
-    }
-
-  for (node = printer_list->backends; node != NULL; node = next)
-    {
-      next = node->next;
-      backend = GTK_PRINT_BACKEND (node->data);
-      if (list_printers_init (printer_list, backend))
-        return;
-    }
-
-  if (wait && printer_list->backends)
-    {
-      printer_list->loop = g_main_loop_new (NULL, FALSE);
-      g_main_loop_run (printer_list->loop);
-    }
-}
-
-GType
-gtk_print_capabilities_get_type (void)
-{
-  static GType etype = 0;
-
-  if (G_UNLIKELY (etype == 0))
-    {
-      static const GFlagsValue values[] = {
-        { GTK_PRINT_CAPABILITY_PAGE_SET, "GTK_PRINT_CAPABILITY_PAGE_SET", "page-set" },
-        { GTK_PRINT_CAPABILITY_COPIES, "GTK_PRINT_CAPABILITY_COPIES", "copies" },
-        { GTK_PRINT_CAPABILITY_COLLATE, "GTK_PRINT_CAPABILITY_COLLATE", "collate" },
-        { GTK_PRINT_CAPABILITY_REVERSE, "GTK_PRINT_CAPABILITY_REVERSE", "reverse" },
-        { GTK_PRINT_CAPABILITY_SCALE, "GTK_PRINT_CAPABILITY_SCALE", "scale" },
-        { GTK_PRINT_CAPABILITY_GENERATE_PDF, "GTK_PRINT_CAPABILITY_GENERATE_PDF", "generate-pdf" },
-        { GTK_PRINT_CAPABILITY_GENERATE_PS, "GTK_PRINT_CAPABILITY_GENERATE_PS", "generate-ps" },
-        { GTK_PRINT_CAPABILITY_PREVIEW, "GTK_PRINT_CAPABILITY_PREVIEW", "preview" },
-       { GTK_PRINT_CAPABILITY_NUMBER_UP, "GTK_PRINT_CAPABILITY_NUMBER_UP", "number-up"},
-        { GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT, "GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT", "number-up-layout" },
-        { 0, NULL, NULL }
-      };
-
-      etype = g_flags_register_static (I_("GtkPrintCapabilities"), values);
-    }
-
-  return etype;
-}
diff --git a/gtk/gtkprinter.h b/gtk/gtkprinter.h
deleted file mode 100644 (file)
index 55e0fe4..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/* GtkPrinter
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <cairo.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_CAPABILITIES (gtk_print_capabilities_get_type ())
-
-/* Note, this type is manually registered with GObject in gtkprinter.c
- * If you add any flags, update the registration as well!
- */
-/**
- * GtkPrintCapabilities:
- * @GTK_PRINT_CAPABILITY_PAGE_SET: Print dialog will offer printing even/odd pages.
- * @GTK_PRINT_CAPABILITY_COPIES: Print dialog will allow to print multiple copies.
- * @GTK_PRINT_CAPABILITY_COLLATE: Print dialog will allow to collate multiple copies.
- * @GTK_PRINT_CAPABILITY_REVERSE: Print dialog will allow to print pages in reverse order.
- * @GTK_PRINT_CAPABILITY_SCALE: Print dialog will allow to scale the output.
- * @GTK_PRINT_CAPABILITY_GENERATE_PDF: The program will send the document to
- *   the printer in PDF format
- * @GTK_PRINT_CAPABILITY_GENERATE_PS: The program will send the document to
- *   the printer in Postscript format
- * @GTK_PRINT_CAPABILITY_PREVIEW: Print dialog will offer a preview
- * @GTK_PRINT_CAPABILITY_NUMBER_UP: Print dialog will offer printing multiple
- *   pages per sheet
- * @GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT: Print dialog will allow to rearrange
- *   pages when printing multiple pages per sheet
- *
- * Specifies which features the print dialog should offer.
- *
- * If neither %GTK_PRINT_CAPABILITY_GENERATE_PDF nor
- * %GTK_PRINT_CAPABILITY_GENERATE_PS is specified, GTK assumes that all
- * formats are supported.
- */
-typedef enum
-{
-  GTK_PRINT_CAPABILITY_PAGE_SET         = 1 << 0,
-  GTK_PRINT_CAPABILITY_COPIES           = 1 << 1,
-  GTK_PRINT_CAPABILITY_COLLATE          = 1 << 2,
-  GTK_PRINT_CAPABILITY_REVERSE          = 1 << 3,
-  GTK_PRINT_CAPABILITY_SCALE            = 1 << 4,
-  GTK_PRINT_CAPABILITY_GENERATE_PDF     = 1 << 5,
-  GTK_PRINT_CAPABILITY_GENERATE_PS      = 1 << 6,
-  GTK_PRINT_CAPABILITY_PREVIEW          = 1 << 7,
-  GTK_PRINT_CAPABILITY_NUMBER_UP        = 1 << 8,
-  GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT = 1 << 9
-} GtkPrintCapabilities;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_print_capabilities_get_type (void) G_GNUC_CONST;
-
-#define GTK_TYPE_PRINTER                  (gtk_printer_get_type ())
-#define GTK_PRINTER(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER, GtkPrinter))
-#define GTK_IS_PRINTER(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER))
-
-typedef struct _GtkPrinter      GtkPrinter;
-typedef struct _GtkPrintBackend GtkPrintBackend;
-
-GDK_AVAILABLE_IN_ALL
-GType                    gtk_printer_get_type              (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkPrinter              *gtk_printer_new                   (const char      *name,
-                                                           GtkPrintBackend *backend,
-                                                           gboolean         virtual_);
-GDK_AVAILABLE_IN_ALL
-GtkPrintBackend         *gtk_printer_get_backend           (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_printer_get_name              (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_printer_get_state_message     (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_printer_get_description       (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_printer_get_location          (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_printer_get_icon_name         (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-int                      gtk_printer_get_job_count         (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_is_active             (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_is_paused             (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_is_accepting_jobs     (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_is_virtual            (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_is_default            (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_accepts_pdf           (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_accepts_ps            (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-GList                   *gtk_printer_list_papers           (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup            *gtk_printer_get_default_page_size (GtkPrinter      *printer);
-GDK_AVAILABLE_IN_ALL
-int                      gtk_printer_compare               (GtkPrinter *a,
-                                                           GtkPrinter *b);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_has_details           (GtkPrinter       *printer);
-GDK_AVAILABLE_IN_ALL
-void                     gtk_printer_request_details       (GtkPrinter       *printer);
-GDK_AVAILABLE_IN_ALL
-GtkPrintCapabilities     gtk_printer_get_capabilities      (GtkPrinter       *printer);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_get_hard_margins      (GtkPrinter       *printer,
-                                                            double           *top,
-                                                            double           *bottom,
-                                                            double           *left,
-                                                            double           *right);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_printer_get_hard_margins_for_paper_size (GtkPrinter       *printer,
-                                                                     GtkPaperSize     *paper_size,
-                                                                     double           *top,
-                                                                     double           *bottom,
-                                                                     double           *left,
-                                                                     double           *right);
-
-/**
- * GtkPrinterFunc:
- * @printer: a `GtkPrinter`
- * @data: (closure): user data passed to gtk_enumerate_printers()
- *
- * The type of function passed to gtk_enumerate_printers().
- *
- * Note that you need to ref @printer, if you want to keep
- * a reference to it after the function has returned.
- *
- * Returns: %TRUE to stop the enumeration, %FALSE to continue
- */
-typedef gboolean (*GtkPrinterFunc) (GtkPrinter *printer,
-                                   gpointer    data);
-
-GDK_AVAILABLE_IN_ALL
-void                     gtk_enumerate_printers        (GtkPrinterFunc   func,
-                                                       gpointer         data,
-                                                       GDestroyNotify   destroy,
-                                                       gboolean         wait);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrinter, g_object_unref)
-
-G_END_DECLS
-
diff --git a/gtk/gtkprinteroption.c b/gtk/gtkprinteroption.c
deleted file mode 100644 (file)
index 91e4bde..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <string.h>
-#include <gmodule.h>
-
-#include "gtkprivate.h"
-#include "gtkprinteroptionprivate.h"
-
-/*****************************************
- *            GtkPrinterOption           *
- *****************************************/
-
-enum {
-  CHANGED,
-  LAST_SIGNAL
-};
-
-enum {
-  PROP_0,
-  PROP_VALUE
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void gtk_printer_option_set_property (GObject      *object,
-                                             guint         prop_id,
-                                             const GValue *value,
-                                             GParamSpec   *pspec);
-static void gtk_printer_option_get_property (GObject      *object,
-                                             guint         prop_id,
-                                             GValue       *value,
-                                             GParamSpec   *pspec);
-
-G_DEFINE_TYPE (GtkPrinterOption, gtk_printer_option, G_TYPE_OBJECT)
-
-static void
-gtk_printer_option_finalize (GObject *object)
-{
-  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
-  int i;
-  
-  g_free (option->name);
-  g_free (option->display_text);
-  g_free (option->value);
-  for (i = 0; i < option->num_choices; i++)
-    {
-      g_free (option->choices[i]);
-      g_free (option->choices_display[i]);
-    }
-  g_free (option->choices);
-  g_free (option->choices_display);
-  g_free (option->group);
-  
-  G_OBJECT_CLASS (gtk_printer_option_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_init (GtkPrinterOption *option)
-{
-  option->value = g_strdup ("");
-  option->activates_default = FALSE;
-}
-
-static void
-gtk_printer_option_class_init (GtkPrinterOptionClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->finalize = gtk_printer_option_finalize;
-  gobject_class->set_property = gtk_printer_option_set_property;
-  gobject_class->get_property = gtk_printer_option_get_property;
-
-  signals[CHANGED] =
-    g_signal_new (I_("changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrinterOptionClass, changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-
-  g_object_class_install_property (G_OBJECT_CLASS (class),
-                                   PROP_VALUE,
-                                   g_param_spec_string ("value", NULL, NULL,
-                                                        "",
-                                                        GTK_PARAM_READWRITE));
-}
-
-GtkPrinterOption *
-gtk_printer_option_new (const char *name, const char *display_text,
-                       GtkPrinterOptionType type)
-{
-  GtkPrinterOption *option;
-
-  option = g_object_new (GTK_TYPE_PRINTER_OPTION, NULL);
-
-  option->name = g_strdup (name);
-  option->display_text = g_strdup (display_text);
-  option->type = type;
-  
-  return option;
-}
-
-static void
-gtk_printer_option_set_property (GObject         *object,
-                                 guint            prop_id,
-                                 const GValue    *value,
-                                 GParamSpec      *pspec)
-{
-  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
-
-  switch (prop_id)
-    {
-    case PROP_VALUE:
-      gtk_printer_option_set (option, g_value_get_string (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_printer_option_get_property (GObject    *object,
-                                 guint       prop_id,
-                                 GValue     *value,
-                                 GParamSpec *pspec)
-{
-  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
-
-  switch (prop_id)
-    {
-    case PROP_VALUE:
-      g_value_set_string (value, option->value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-emit_changed (GtkPrinterOption *option)
-{
-  g_signal_emit (option, signals[CHANGED], 0);
-}
-
-void
-gtk_printer_option_set (GtkPrinterOption *option,
-                       const char *value)
-{
-  if (value == NULL)
-    value = "";
-  
-  if (strcmp (option->value, value) == 0)
-    return;
-
-  if ((option->type == GTK_PRINTER_OPTION_TYPE_PICKONE ||
-       option->type == GTK_PRINTER_OPTION_TYPE_ALTERNATIVE))
-    {
-      int i;
-      
-      for (i = 0; i < option->num_choices; i++)
-       {
-         if (g_ascii_strcasecmp (value, option->choices[i]) == 0)
-           {
-             value = option->choices[i];
-             break;
-           }
-       }
-
-      if (i == option->num_choices)
-       return; /* Not found in available choices */
-    }
-          
-  g_free (option->value);
-  option->value = g_strdup (value);
-  
-  emit_changed (option);
-}
-
-void
-gtk_printer_option_set_boolean (GtkPrinterOption *option,
-                               gboolean value)
-{
-  gtk_printer_option_set (option, value ? "True" : "False");
-}
-
-void
-gtk_printer_option_set_has_conflict  (GtkPrinterOption *option,
-                                     gboolean  has_conflict)
-{
-  has_conflict = has_conflict != 0;
-  
-  if (option->has_conflict == has_conflict)
-    return;
-
-  option->has_conflict = has_conflict;
-  emit_changed (option);
-}
-
-void
-gtk_printer_option_clear_has_conflict (GtkPrinterOption     *option)
-{
-  gtk_printer_option_set_has_conflict  (option, FALSE);
-}
-
-void
-gtk_printer_option_allocate_choices (GtkPrinterOption     *option,
-                                    int num)
-{
-  g_free (option->choices);
-  g_free (option->choices_display);
-
-  option->num_choices = num;
-  if (num == 0)
-    {
-      option->choices = NULL;
-      option->choices_display = NULL;
-    }
-  else
-    {
-      option->choices = g_new0 (char *, num);
-      option->choices_display = g_new0 (char *, num);
-    }
-}
-
-void
-gtk_printer_option_choices_from_array (GtkPrinterOption   *option,
-                                      int                 num_choices,
-                                      const char        **choices,
-                                      const char        **choices_display)
-{
-  int i;
-  
-  gtk_printer_option_allocate_choices (option, num_choices);
-  for (i = 0; i < num_choices; i++)
-    {
-      option->choices[i] = g_strdup (choices[i]);
-      option->choices_display[i] = g_strdup (choices_display[i]);
-    }
-}
-
-gboolean
-gtk_printer_option_has_choice (GtkPrinterOption     *option,
-                              const char           *choice)
-{
-  int i;
-  
-  for (i = 0; i < option->num_choices; i++)
-    {
-      if (strcmp (option->choices[i], choice) == 0)
-       return TRUE;
-    }
-  
-  return FALSE;
-}
-
-void
-gtk_printer_option_set_activates_default (GtkPrinterOption *option,
-                                         gboolean          activates)
-{
-  g_return_if_fail (GTK_IS_PRINTER_OPTION (option));
-
-  option->activates_default = activates;
-}
-
-gboolean
-gtk_printer_option_get_activates_default (GtkPrinterOption *option)
-{
-  g_return_val_if_fail (GTK_IS_PRINTER_OPTION (option), FALSE);
-
-  return option->activates_default;
-}
diff --git a/gtk/gtkprinteroptionprivate.h b/gtk/gtkprinteroptionprivate.h
deleted file mode 100644 (file)
index 0578e30..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION             (gtk_printer_option_get_type ())
-#define GTK_PRINTER_OPTION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION, GtkPrinterOption))
-#define GTK_IS_PRINTER_OPTION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION))
-
-typedef struct _GtkPrinterOption       GtkPrinterOption;
-typedef struct _GtkPrinterOptionClass  GtkPrinterOptionClass;
-
-#define GTK_PRINTER_OPTION_GROUP_IMAGE_QUALITY "ImageQuality"
-#define GTK_PRINTER_OPTION_GROUP_FINISHING "Finishing"
-
-typedef enum {
-  GTK_PRINTER_OPTION_TYPE_BOOLEAN,
-  GTK_PRINTER_OPTION_TYPE_PICKONE,
-  GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD,
-  GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE,
-  GTK_PRINTER_OPTION_TYPE_PICKONE_REAL,
-  GTK_PRINTER_OPTION_TYPE_PICKONE_INT,
-  GTK_PRINTER_OPTION_TYPE_PICKONE_STRING,
-  GTK_PRINTER_OPTION_TYPE_ALTERNATIVE,
-  GTK_PRINTER_OPTION_TYPE_STRING,
-  GTK_PRINTER_OPTION_TYPE_FILESAVE,
-  GTK_PRINTER_OPTION_TYPE_INFO
-} GtkPrinterOptionType;
-
-struct _GtkPrinterOption
-{
-  GObject parent_instance;
-
-  char *name;
-  char *display_text;
-  GtkPrinterOptionType type;
-
-  char *value;
-
-  int num_choices;
-  char **choices;
-  char **choices_display;
-
-  gboolean activates_default;
-
-  gboolean has_conflict;
-  char *group;
-};
-
-struct _GtkPrinterOptionClass
-{
-  GObjectClass parent_class;
-
-  void (*changed) (GtkPrinterOption *option);
-
-  /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
-};
-
-GDK_AVAILABLE_IN_ALL
-GType   gtk_printer_option_get_type       (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOption *gtk_printer_option_new                    (const char           *name,
-                                                            const char           *display_text,
-                                                            GtkPrinterOptionType  type);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_set                    (GtkPrinterOption     *option,
-                                                            const char           *value);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_set_has_conflict       (GtkPrinterOption     *option,
-                                                            gboolean              has_conflict);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_clear_has_conflict     (GtkPrinterOption     *option);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_set_boolean            (GtkPrinterOption     *option,
-                                                            gboolean              value);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_allocate_choices       (GtkPrinterOption     *option,
-                                                            int                   num);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_choices_from_array     (GtkPrinterOption     *option,
-                                                             int                   num_choices,
-                                                             const char           **choices,
-                                                             const char           **choices_display);
-GDK_AVAILABLE_IN_ALL
-gboolean          gtk_printer_option_has_choice             (GtkPrinterOption     *option,
-                                                           const char           *choice);
-GDK_AVAILABLE_IN_ALL
-void              gtk_printer_option_set_activates_default (GtkPrinterOption     *option,
-                                                           gboolean              activates);
-GDK_AVAILABLE_IN_ALL
-gboolean          gtk_printer_option_get_activates_default (GtkPrinterOption     *option);
-
-
-G_END_DECLS
-
-
-
diff --git a/gtk/gtkprinteroptionset.c b/gtk/gtkprinteroptionset.c
deleted file mode 100644 (file)
index 288fda6..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <string.h>
-#include <glib.h>
-#include <gmodule.h>
-
-#include "gtkprinteroptionsetprivate.h"
-#include "gtkprivate.h"
-
-/*****************************************
- *         GtkPrinterOptionSet    *
- *****************************************/
-
-enum {
-  CHANGED,
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* ugly side-effect of aliasing */
-#undef gtk_printer_option_set
-
-G_DEFINE_TYPE (GtkPrinterOptionSet, gtk_printer_option_set, G_TYPE_OBJECT)
-
-static void
-gtk_printer_option_set_finalize (GObject *object)
-{
-  GtkPrinterOptionSet *set = GTK_PRINTER_OPTION_SET (object);
-
-  g_hash_table_destroy (set->hash);
-  g_ptr_array_foreach (set->array, (GFunc)g_object_unref, NULL);
-  g_ptr_array_free (set->array, TRUE);
-  
-  G_OBJECT_CLASS (gtk_printer_option_set_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_set_init (GtkPrinterOptionSet *set)
-{
-  set->array = g_ptr_array_new ();
-  set->hash = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-gtk_printer_option_set_class_init (GtkPrinterOptionSetClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->finalize = gtk_printer_option_set_finalize;
-
-  signals[CHANGED] =
-    g_signal_new (I_("changed"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrinterOptionSetClass, changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-}
-
-
-static void
-emit_changed (GtkPrinterOptionSet *set)
-{
-  g_signal_emit (set, signals[CHANGED], 0);
-}
-
-GtkPrinterOptionSet *
-gtk_printer_option_set_new (void)
-{
-  return g_object_new (GTK_TYPE_PRINTER_OPTION_SET, NULL);
-}
-
-void
-gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
-                              GtkPrinterOption    *option)
-{
-  int i;
-  
-  for (i = 0; i < set->array->len; i++)
-    {
-      if (g_ptr_array_index (set->array, i) == option)
-       {
-         g_ptr_array_remove_index (set->array, i);
-         g_hash_table_remove (set->hash, option->name);
-         g_signal_handlers_disconnect_by_func (option, emit_changed, set);
-
-         g_object_unref (option);
-         break;
-       }
-    }
-}
-
-void
-gtk_printer_option_set_add (GtkPrinterOptionSet *set,
-                           GtkPrinterOption    *option)
-{
-  g_object_ref (option);
-  
-  if (gtk_printer_option_set_lookup (set, option->name))
-    gtk_printer_option_set_remove (set, option);
-    
-  g_ptr_array_add (set->array, option);
-  g_hash_table_insert (set->hash, option->name, option);
-  g_signal_connect_object (option, "changed", G_CALLBACK (emit_changed), set, G_CONNECT_SWAPPED);
-}
-
-GtkPrinterOption *
-gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
-                              const char          *name)
-{
-  gpointer ptr;
-
-  ptr = g_hash_table_lookup (set->hash, name);
-
-  return GTK_PRINTER_OPTION (ptr);
-}
-
-void
-gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set)
-{
-  gtk_printer_option_set_foreach (set,
-                                 (GtkPrinterOptionSetFunc)gtk_printer_option_clear_has_conflict,
-                                 NULL);
-}
-
-/**
- * gtk_printer_option_set_get_groups:
- * @set: a `GtkPrinterOptionSet`
- *
- * Gets the groups in this set.
- *
- * Returns: (element-type utf8) (transfer full): a list of group names.
- */
-GList *
-gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set)
-{
-  GtkPrinterOption *option;
-  GList *list = NULL;
-  int i;
-
-  for (i = 0; i < set->array->len; i++)
-    {
-      option = g_ptr_array_index (set->array, i);
-
-      if (g_list_find_custom (list, option->group, (GCompareFunc)g_strcmp0) == NULL)
-       list = g_list_prepend (list, g_strdup (option->group));
-    }
-
-  return g_list_reverse (list);
-}
-
-void
-gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet     *set,
-                                        const char              *group,
-                                        GtkPrinterOptionSetFunc  func,
-                                        gpointer                 user_data)
-{
-  GtkPrinterOption *option;
-  int i;
-
-  for (i = 0; i < set->array->len; i++)
-    {
-      option = g_ptr_array_index (set->array, i);
-
-      if (group == NULL || g_strcmp0 (group, option->group) == 0)
-       func (option, user_data);
-    }
-}
-
-void
-gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
-                               GtkPrinterOptionSetFunc func,
-                               gpointer user_data)
-{
-  gtk_printer_option_set_foreach_in_group (set, NULL, func, user_data);
-}
diff --git a/gtk/gtkprinteroptionsetprivate.h b/gtk/gtkprinteroptionsetprivate.h
deleted file mode 100644 (file)
index 416a82a..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-/* This is a "semi-private" header; it is meant only for
- * alternate GtkPrintDialog backend modules; no stability guarantees
- * are made at this point
- */
-#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
-#error "GtkPrintBackend is not supported API for general use"
-#endif
-
-#include <glib-object.h>
-#include <gdk/gdk.h>
-#include "gtkprinteroptionprivate.h"
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION_SET             (gtk_printer_option_set_get_type ())
-#define GTK_PRINTER_OPTION_SET(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_SET, GtkPrinterOptionSet))
-#define GTK_IS_PRINTER_OPTION_SET(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_SET))
-
-typedef struct _GtkPrinterOptionSet       GtkPrinterOptionSet;
-typedef struct _GtkPrinterOptionSetClass  GtkPrinterOptionSetClass;
-
-struct _GtkPrinterOptionSet
-{
-  GObject parent_instance;
-
-  /*< private >*/
-  GPtrArray *array;
-  GHashTable *hash;
-};
-
-struct _GtkPrinterOptionSetClass
-{
-  GObjectClass parent_class;
-
-  void (*changed) (GtkPrinterOptionSet *option);
-
-
-  /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
-};
-
-typedef void (*GtkPrinterOptionSetFunc) (GtkPrinterOption  *option,
-                                        gpointer           user_data);
-
-
-GDK_AVAILABLE_IN_ALL
-GType   gtk_printer_option_set_get_type       (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOptionSet *gtk_printer_option_set_new              (void);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_printer_option_set_add              (GtkPrinterOptionSet     *set,
-                                                             GtkPrinterOption        *option);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_printer_option_set_remove           (GtkPrinterOptionSet     *set,
-                                                             GtkPrinterOption        *option);
-GDK_AVAILABLE_IN_ALL
-GtkPrinterOption *   gtk_printer_option_set_lookup           (GtkPrinterOptionSet     *set,
-                                                             const char              *name);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_printer_option_set_foreach          (GtkPrinterOptionSet     *set,
-                                                             GtkPrinterOptionSetFunc  func,
-                                                             gpointer                 user_data);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_printer_option_set_clear_conflicts  (GtkPrinterOptionSet     *set);
-GDK_AVAILABLE_IN_ALL
-GList *              gtk_printer_option_set_get_groups       (GtkPrinterOptionSet     *set);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet     *set,
-                                                             const char              *group,
-                                                             GtkPrinterOptionSetFunc  func,
-                                                             gpointer                 user_data);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c
deleted file mode 100644 (file)
index c14a675..0000000
+++ /dev/null
@@ -1,1192 +0,0 @@
-/* GtkPrinterOptionWidget
- * Copyright (C) 2006 Alexander Larsson  <alexl@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include <glib/gi18n-lib.h>
-#include "gtkcheckbutton.h"
-#include "gtkdropdown.h"
-#include "gtklistitem.h"
-#include "gtksignallistitemfactory.h"
-#include "gtkentry.h"
-#include "gtkfiledialog.h"
-#include "gtkimage.h"
-#include "gtklabel.h"
-#include "gtkcheckbutton.h"
-#include "gtkgrid.h"
-#include "gtkorientable.h"
-#include "gtkprivate.h"
-#include "gtkstringlist.h"
-
-#include "gtkprinteroptionwidgetprivate.h"
-
-/* This defines the max file length that the file chooser
- * button should display. The total length will be
- * FILENAME_LENGTH_MAX+3 because the truncated name is prefixed
- * with “...”.
- */
-#define FILENAME_LENGTH_MAX 27
-
-static void gtk_printer_option_widget_finalize (GObject *object);
-
-static void deconstruct_widgets (GtkPrinterOptionWidget *widget);
-static void construct_widgets   (GtkPrinterOptionWidget *widget);
-static void update_widgets      (GtkPrinterOptionWidget *widget);
-
-static char *trim_long_filename (const char *filename);
-
-struct GtkPrinterOptionWidgetPrivate
-{
-  GtkPrinterOption *source;
-  gulong source_changed_handler;
-
-  GtkWidget *check;
-  GtkWidget *combo;
-  GtkWidget *entry;
-  GtkWidget *image;
-  GtkWidget *label;
-  GtkWidget *info_label;
-  GtkWidget *box;
-  GtkWidget *button;
-
-  /* the last location for save to file, that the user selected */
-  GFile *last_location;
-};
-
-enum {
-  CHANGED,
-  LAST_SIGNAL
-};
-
-enum {
-  PROP_0,
-  PROP_SOURCE
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_BOX)
-
-static void gtk_printer_option_widget_set_property (GObject      *object,
-                                                   guint         prop_id,
-                                                   const GValue *value,
-                                                   GParamSpec   *pspec);
-static void gtk_printer_option_widget_get_property (GObject      *object,
-                                                   guint         prop_id,
-                                                   GValue       *value,
-                                                   GParamSpec   *pspec);
-static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
-                                                            gboolean   group_cycling);
-
-static void
-gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class)
-{
-  GObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-
-  object_class = (GObjectClass *) class;
-  widget_class = (GtkWidgetClass *) class;
-
-  object_class->finalize = gtk_printer_option_widget_finalize;
-  object_class->set_property = gtk_printer_option_widget_set_property;
-  object_class->get_property = gtk_printer_option_widget_get_property;
-
-  widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate;
-
-  signals[CHANGED] =
-    g_signal_new (I_("changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrinterOptionWidgetClass, changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-
-  g_object_class_install_property (object_class,
-                                   PROP_SOURCE,
-                                   g_param_spec_object ("source", NULL, NULL,
-                                                       GTK_TYPE_PRINTER_OPTION,
-                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-}
-
-static void
-gtk_printer_option_widget_init (GtkPrinterOptionWidget *widget)
-{
-  widget->priv = gtk_printer_option_widget_get_instance_private (widget);
-
-  gtk_box_set_spacing (GTK_BOX (widget), 12);
-}
-
-static void
-gtk_printer_option_widget_finalize (GObject *object)
-{
-  GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  if (priv->source)
-    {
-      g_signal_handler_disconnect (priv->source,
-                                  priv->source_changed_handler);
-      g_object_unref (priv->source);
-      priv->source = NULL;
-    }
-
-  G_OBJECT_CLASS (gtk_printer_option_widget_parent_class)->finalize (object);
-}
-
-static void
-gtk_printer_option_widget_set_property (GObject         *object,
-                                       guint            prop_id,
-                                       const GValue    *value,
-                                       GParamSpec      *pspec)
-{
-  GtkPrinterOptionWidget *widget;
-
-  widget = GTK_PRINTER_OPTION_WIDGET (object);
-
-  switch (prop_id)
-    {
-    case PROP_SOURCE:
-      gtk_printer_option_widget_set_source (widget, g_value_get_object (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_printer_option_widget_get_property (GObject    *object,
-                                       guint       prop_id,
-                                       GValue     *value,
-                                       GParamSpec *pspec)
-{
-  GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  switch (prop_id)
-    {
-    case PROP_SOURCE:
-      g_value_set_object (value, priv->source);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static gboolean
-gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
-                                            gboolean   group_cycling)
-{
-  GtkPrinterOptionWidget *powidget = GTK_PRINTER_OPTION_WIDGET (widget);
-  GtkPrinterOptionWidgetPrivate *priv = powidget->priv;
-
-  if (priv->check)
-    return gtk_widget_mnemonic_activate (priv->check, group_cycling);
-  if (priv->combo)
-    return gtk_widget_mnemonic_activate (priv->combo, group_cycling);
-  if (priv->entry)
-    return gtk_widget_mnemonic_activate (priv->entry, group_cycling);
-  if (priv->button)
-    return gtk_widget_mnemonic_activate (priv->button, group_cycling);
-
-  return FALSE;
-}
-
-static void
-emit_changed (GtkPrinterOptionWidget *widget)
-{
-  g_signal_emit (widget, signals[CHANGED], 0);
-}
-
-GtkWidget *
-gtk_printer_option_widget_new (GtkPrinterOption *source)
-{
-  return g_object_new (GTK_TYPE_PRINTER_OPTION_WIDGET, "source", source, NULL);
-}
-
-static void
-source_changed_cb (GtkPrinterOption *source,
-                  GtkPrinterOptionWidget  *widget)
-{
-  update_widgets (widget);
-  emit_changed (widget);
-}
-
-void
-gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget,
-                                     GtkPrinterOption       *source)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  if (source)
-    g_object_ref (source);
-
-  if (priv->source)
-    {
-      g_signal_handler_disconnect (priv->source,
-                                  priv->source_changed_handler);
-      g_object_unref (priv->source);
-    }
-
-  priv->source = source;
-
-  if (source)
-    priv->source_changed_handler =
-      g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), widget);
-
-  construct_widgets (widget);
-  update_widgets (widget);
-
-  g_object_notify (G_OBJECT (widget), "source");
-}
-
-#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ())
-G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject)
-
-struct _GtkStringPair {
-  GObject parent_instance;
-  char *id;
-  char *string;
-};
-
-enum {
-  PROP_ID = 1,
-  PROP_STRING,
-  PROP_NUM_PROPERTIES
-};
-
-G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT);
-
-static void
-gtk_string_pair_init (GtkStringPair *pair)
-{
-}
-
-static void
-gtk_string_pair_finalize (GObject *object)
-{
-  GtkStringPair *pair = GTK_STRING_PAIR (object);
-
-  g_free (pair->id);
-  g_free (pair->string);
-
-  G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object);
-}
-
-static void
-gtk_string_pair_set_property (GObject      *object,
-                              guint         property_id,
-                              const GValue *value,
-                              GParamSpec   *pspec)
-{
-  GtkStringPair *pair = GTK_STRING_PAIR (object);
-
-  switch (property_id)
-    {
-    case PROP_STRING:
-      g_free (pair->string);
-      pair->string = g_value_dup_string (value);
-      break;
-
-    case PROP_ID:
-      g_free (pair->id);
-      pair->id = g_value_dup_string (value);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_string_pair_get_property (GObject      *object,
-                              guint         property_id,
-                              GValue       *value,
-                              GParamSpec   *pspec)
-{
-  GtkStringPair *pair = GTK_STRING_PAIR (object);
-
-  switch (property_id)
-    {
-    case PROP_STRING:
-      g_value_set_string (value, pair->string);
-      break;
-
-    case PROP_ID:
-      g_value_set_string (value, pair->id);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_string_pair_class_init (GtkStringPairClass *class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  GParamSpec *pspec;
-
-  object_class->finalize = gtk_string_pair_finalize;
-  object_class->set_property = gtk_string_pair_set_property;
-  object_class->get_property = gtk_string_pair_get_property;
-
-  pspec = g_param_spec_string ("string", NULL, NULL,
-                               NULL,
-                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_property (object_class, PROP_STRING, pspec);
-
-  pspec = g_param_spec_string ("id", NULL, NULL,
-                               NULL,
-                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_property (object_class, PROP_ID, pspec);
-}
-
-static GtkStringPair *
-gtk_string_pair_new (const char *id,
-                     const char *string)
-{
-  return g_object_new (GTK_TYPE_STRING_PAIR,
-                       "id", id,
-                       "string", string,
-                       NULL);
-}
-
-static const char *
-gtk_string_pair_get_string (GtkStringPair *pair)
-{
-  return pair->string;
-}
-
-static const char *
-gtk_string_pair_get_id (GtkStringPair *pair)
-{
-  return pair->id;
-}
-
-static void
-combo_box_set_model (GtkWidget *combo_box)
-{
-  GListStore *store;
-
-  store = g_list_store_new (GTK_TYPE_STRING_PAIR);
-  gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store));
-  g_object_unref (store);
-}
-
-static void
-setup_no_item (GtkSignalListItemFactory *factory,
-               GtkListItem              *item)
-{
-}
-
-static void
-setup_list_item (GtkSignalListItemFactory *factory,
-                 GtkListItem              *item)
-{
-  GtkWidget *label;
-
-  label = gtk_label_new ("");
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_list_item (GtkSignalListItemFactory *factory,
-                GtkListItem              *item)
-{
-  GtkStringPair *pair;
-  GtkWidget *label;
-
-  pair = gtk_list_item_get_item (item);
-  label = gtk_list_item_get_child (item);
-
-  gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair));
-}
-
-static void
-combo_box_set_view (GtkWidget *combo_box)
-{
-  GtkListItemFactory *factory;
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory);
-  g_object_unref (factory);
-}
-
-static void
-selected_changed (GtkDropDown *dropdown,
-                  GParamSpec *pspec,
-                  gpointer data)
-{
-  GListModel *model;
-  guint selected;
-  GtkStringPair *pair;
-  GtkWidget *entry = data;
-
-  model = gtk_drop_down_get_model (dropdown);
-  selected = gtk_drop_down_get_selected (dropdown);
-
-  pair = g_list_model_get_item (model, selected);
-  if (pair)
-    {
-      gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair));
-      g_object_unref (pair);
-    }
-  else
-    gtk_editable_set_text (GTK_EDITABLE (entry), "");
-
-}
-
-static GtkWidget *
-combo_box_entry_new (void)
-{
-  GtkWidget *hbox, *entry, *button;
-  GtkListItemFactory *factory;
-
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-  gtk_widget_add_css_class (hbox, "linked");
-
-  entry = gtk_entry_new ();
-  button = gtk_drop_down_new (NULL, NULL);
-  combo_box_set_model (button);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory);
-  g_object_unref (factory);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
-  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory);
-  g_object_unref (factory);
-
-  g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry);
-
-  gtk_box_append (GTK_BOX (hbox), entry);
-  gtk_box_append (GTK_BOX (hbox), button);
-
-  return hbox;
-}
-
-static GtkWidget *
-combo_box_new (void)
-{
-  GtkWidget *combo_box;
-
-  combo_box = gtk_drop_down_new (NULL, NULL);
-
-  combo_box_set_model (combo_box);
-  combo_box_set_view (combo_box);
-
-  return combo_box;
-}
-
-static void
-combo_box_append (GtkWidget   *combo,
-                  const char *display_text,
-                  const char *value)
-{
-  GtkWidget *dropdown;
-  GListModel *model;
-  GtkStringPair *object;
-
-  if (GTK_IS_DROP_DOWN (combo))
-    dropdown = combo;
-  else
-    dropdown = gtk_widget_get_last_child (combo);
-
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
-
-  object = gtk_string_pair_new (value, display_text);
-  g_list_store_append (G_LIST_STORE (model), object);
-  g_object_unref (object);
-}
-
-static void
-combo_box_set (GtkWidget   *combo,
-               const char *value)
-{
-  GtkWidget *dropdown;
-  GListModel *model;
-  guint i;
-
-  if (GTK_IS_DROP_DOWN (combo))
-    dropdown = combo;
-  else
-    dropdown = gtk_widget_get_last_child (combo);
-
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
-
-  for (i = 0; i < g_list_model_get_n_items (model); i++)
-    {
-      GtkStringPair *item = g_list_model_get_item (model, i);
-      if (strcmp (value, gtk_string_pair_get_id (item)) == 0)
-        {
-          gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
-          g_object_unref (item);
-          break;
-        }
-      g_object_unref (item);
-    }
-}
-
-static char *
-combo_box_get (GtkWidget *combo, gboolean *custom)
-{
-  GtkWidget *dropdown;
-  GListModel *model;
-  guint selected;
-  gpointer item;
-  const char *id;
-  const char *string;
-
-  if (GTK_IS_DROP_DOWN (combo))
-    dropdown = combo;
-  else
-    dropdown = gtk_widget_get_last_child (combo);
-
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
-  item = g_list_model_get_item (model, selected);
-  if (item)
-    {
-      id = gtk_string_pair_get_id (item);
-      string = gtk_string_pair_get_string (item);
-      g_object_unref (item);
-    }
-  else
-    {
-      id = "";
-      string = NULL;
-    }
-
-  if (dropdown == combo) // no entry
-    {
-      *custom = FALSE;
-      return g_strdup (id);
-    }
-  else
-    {
-      const char *text;
-
-      text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo)));
-      if (g_strcmp0 (text, string) == 0)
-        {
-          *custom = FALSE;
-          return g_strdup (id);
-        }
-      else
-        {
-          *custom = TRUE;
-          return g_strdup (text);
-        }
-    }
-}
-
-static void
-deconstruct_widgets (GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  g_clear_pointer (&priv->check, gtk_widget_unparent);
-  g_clear_pointer (&priv->combo, gtk_widget_unparent);
-  g_clear_pointer (&priv->entry, gtk_widget_unparent);
-  g_clear_pointer (&priv->image, gtk_widget_unparent);
-  g_clear_pointer (&priv->label, gtk_widget_unparent);
-  g_clear_pointer (&priv->info_label, gtk_widget_unparent);
-}
-
-static void
-check_toggled_cb (GtkCheckButton         *check_button,
-                 GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  g_signal_handler_block (priv->source, priv->source_changed_handler);
-  gtk_printer_option_set_boolean (priv->source,
-                                  gtk_check_button_get_active (check_button));
-  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-  emit_changed (widget);
-}
-
-static void
-dialog_response_callback (GObject *source,
-                          GAsyncResult *result,
-                          gpointer data)
-{
-  GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
-  GtkPrinterOptionWidget *widget = data;
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  GFile *new_location = NULL;
-  char *uri = NULL;
-
-  new_location = gtk_file_dialog_save_finish (dialog, result, NULL);
-  if (new_location)
-    {
-      GFileInfo *info;
-
-      info = g_file_query_info (new_location,
-                                "standard::display-name",
-                                0,
-                                NULL,
-                                NULL);
-      if (info != NULL)
-        {
-          const char *filename_utf8 = g_file_info_get_display_name (info);
-
-          char *filename_short = trim_long_filename (filename_utf8);
-          gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
-
-          g_free (filename_short);
-          g_object_unref (info);
-        }
-      else
-        {
-          const char *path = g_file_peek_path (new_location);
-          char *filename_utf8 = g_utf8_make_valid (path, -1);
-
-          char *filename_short = trim_long_filename (filename_utf8);
-          gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
-
-          g_free (filename_short);
-          g_free (filename_utf8);
-        }
-    }
-
-  if (new_location)
-    uri = g_file_get_uri (new_location);
-  else
-    uri = g_file_get_uri (priv->last_location);
-
-  if (uri != NULL)
-    {
-      gtk_printer_option_set (priv->source, uri);
-      emit_changed (widget);
-      g_free (uri);
-    }
-
-  g_clear_object (&new_location);
-  g_clear_object (&priv->last_location);
-
-  /* unblock the handler which was blocked in the filesave_choose_cb function */
-  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-}
-
-static void
-filesave_choose_cb (GtkWidget              *button,
-                    GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  GtkFileDialog *dialog;
-
-  /* this will be unblocked in the dialog_response_callback function */
-  g_signal_handler_block (priv->source, priv->source_changed_handler);
-
-  dialog = gtk_file_dialog_new ();
-  gtk_file_dialog_set_title (dialog, _("Select a filename"));
-
-  /* select the current filename in the dialog */
-  if (priv->source != NULL && priv->source->value != NULL)
-    {
-      priv->last_location = g_file_new_for_uri (priv->source->value);
-      if (priv->last_location)
-        {
-          if (g_file_query_file_type (priv->last_location, 0, NULL) == G_FILE_TYPE_DIRECTORY)
-            gtk_file_dialog_set_initial_folder (dialog, priv->last_location);
-          else
-            gtk_file_dialog_set_initial_file (dialog, priv->last_location);
-        }
-    }
-
-  gtk_file_dialog_save (dialog,
-                        GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (widget))),
-                        NULL,
-                        dialog_response_callback, widget);
-}
-
-static char *
-filter_numeric (const char *val,
-                gboolean     allow_neg,
-               gboolean     allow_dec,
-                gboolean    *changed_out)
-{
-  char *filtered_val;
-  int i, j;
-  int len = strlen (val);
-  gboolean dec_set = FALSE;
-
-  filtered_val = g_malloc (len + 1);
-
-  for (i = 0, j = 0; i < len; i++)
-    {
-      if (isdigit (val[i]))
-        {
-          filtered_val[j] = val[i];
-         j++;
-       }
-      else if (allow_dec && !dec_set &&
-               (val[i] == '.' || val[i] == ','))
-        {
-         /* allow one period or comma
-          * we should be checking locals
-          * but this is good enough for now
-          */
-          filtered_val[j] = val[i];
-         dec_set = TRUE;
-         j++;
-       }
-      else if (allow_neg && i == 0 && val[0] == '-')
-        {
-          filtered_val[0] = val[0];
-         j++;
-       }
-    }
-
-  filtered_val[j] = '\0';
-  *changed_out = !(i == j);
-
-  return filtered_val;
-}
-
-static void
-combo_changed_cb (GtkWidget              *combo,
-                  GParamSpec             *pspec,
-                 GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  char *value;
-  char *filtered_val = NULL;
-  gboolean changed;
-  gboolean custom = TRUE;
-
-  g_signal_handler_block (priv->source, priv->source_changed_handler);
-
-  value = combo_box_get (priv->combo, &custom);
-
-  /* Handle constraints if the user entered a custom value. */
-  if (custom)
-    {
-      switch (priv->source->type)
-        {
-        case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
-          filtered_val = filter_numeric (value, FALSE, FALSE, &changed);
-          break;
-        case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
-          filtered_val = filter_numeric (value, TRUE, FALSE, &changed);
-          break;
-        case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
-          filtered_val = filter_numeric (value, TRUE, TRUE, &changed);
-          break;
-        case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
-        case GTK_PRINTER_OPTION_TYPE_PICKONE:
-        case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
-        case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
-        case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
-        case GTK_PRINTER_OPTION_TYPE_STRING:
-        case GTK_PRINTER_OPTION_TYPE_FILESAVE:
-        case GTK_PRINTER_OPTION_TYPE_INFO:
-        default:
-          break;
-        }
-    }
-
-  if (filtered_val)
-    {
-      g_free (value);
-
-      if (changed)
-        {
-          GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
-          gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val);
-        }
-      value = filtered_val;
-    }
-
-  if (value)
-    gtk_printer_option_set (priv->source, value);
-  g_free (value);
-  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-  emit_changed (widget);
-}
-
-static void
-entry_changed_cb (GtkWidget              *entry,
-                 GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  const char *value;
-
-  g_signal_handler_block (priv->source, priv->source_changed_handler);
-  value = gtk_editable_get_text (GTK_EDITABLE (entry));
-  if (value)
-    gtk_printer_option_set (priv->source, value);
-  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-  emit_changed (widget);
-}
-
-
-static void
-radio_changed_cb (GtkWidget              *button,
-                 GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  char *value;
-
-  g_signal_handler_block (priv->source, priv->source_changed_handler);
-  value = g_object_get_data (G_OBJECT (button), "value");
-  if (value)
-    gtk_printer_option_set (priv->source, value);
-  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
-  emit_changed (widget);
-}
-
-static void
-alternative_set (GtkWidget   *box,
-                 const char *value)
-{
-  GtkWidget *child;
-
-  for (child = gtk_widget_get_first_child (box);
-       child != NULL;
-       child = gtk_widget_get_next_sibling (child))
-    {
-      char *v = g_object_get_data (G_OBJECT (child), "value");
-
-      if (strcmp (value, v) == 0)
-        {
-          gtk_check_button_set_active (GTK_CHECK_BUTTON (child), TRUE);
-          break;
-        }
-    }
-}
-
-static void
-alternative_append (GtkWidget              *box,
-                   const char             *label,
-                    const char             *value,
-                   GtkPrinterOptionWidget *widget,
-                   GtkWidget              **group)
-{
-  GtkWidget *button;
-
-  button = gtk_check_button_new_with_label (label);
-  if (*group)
-    gtk_check_button_set_group (GTK_CHECK_BUTTON (button), GTK_CHECK_BUTTON (*group));
-  else
-    *group = button;
-
-  gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
-  gtk_box_append (GTK_BOX (box), button);
-
-  g_object_set_data (G_OBJECT (button), "value", (gpointer)value);
-  g_signal_connect (button, "toggled", G_CALLBACK (radio_changed_cb), widget);
-}
-
-static void
-construct_widgets (GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  GtkPrinterOption *source;
-  char *text;
-  int i;
-  GtkWidget *group;
-
-  source = priv->source;
-
-  deconstruct_widgets (widget);
-
-  gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
-
-  if (source == NULL)
-    {
-      const char * strings[2];
-      strings[0] = _("Not available");
-      strings[1] = NULL;
-      priv->combo = gtk_drop_down_new_from_strings (strings);
-      gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
-      gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
-      gtk_box_append (GTK_BOX (widget), priv->combo);
-    }
-  else switch (source->type)
-    {
-    case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
-      priv->check = gtk_check_button_new_with_mnemonic (source->display_text);
-      g_signal_connect (priv->check, "toggled", G_CALLBACK (check_toggled_cb), widget);
-      gtk_box_append (GTK_BOX (widget), priv->check);
-      break;
-    case GTK_PRINTER_OPTION_TYPE_PICKONE:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
-      if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE)
-        {
-          priv->combo = combo_box_new ();
-        }
-      else
-        {
-          priv->combo = combo_box_entry_new ();
-
-          if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ||
-              source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
-            {
-              GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
-              gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
-            }
-        }
-
-      for (i = 0; i < source->num_choices; i++)
-        combo_box_append (priv->combo,
-                          source->choices_display[i],
-                          source->choices[i]);
-      gtk_box_append (GTK_BOX (widget), priv->combo);
-      if (GTK_IS_DROP_DOWN (priv->combo))
-        g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget);
-      else
-        g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK (combo_changed_cb), widget);
-
-      text = g_strdup_printf ("%s:", source->display_text);
-      priv->label = gtk_label_new_with_mnemonic (text);
-      g_free (text);
-      break;
-
-    case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
-      group = NULL;
-      priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-      gtk_widget_set_valign (priv->box, GTK_ALIGN_BASELINE_FILL);
-      gtk_box_append (GTK_BOX (widget), priv->box);
-      for (i = 0; i < source->num_choices; i++)
-        {
-          alternative_append (priv->box,
-                              source->choices_display[i],
-                              source->choices[i],
-                              widget,
-                              &group);
-          /* for mnemonic activation */
-          if (i == 0)
-            priv->button = group;
-        }
-
-      if (source->display_text)
-       {
-         text = g_strdup_printf ("%s:", source->display_text);
-         priv->label = gtk_label_new_with_mnemonic (text);
-          gtk_widget_set_valign (priv->label, GTK_ALIGN_BASELINE_FILL);
-         g_free (text);
-       }
-      break;
-
-    case GTK_PRINTER_OPTION_TYPE_STRING:
-      priv->entry = gtk_entry_new ();
-      gtk_entry_set_activates_default (GTK_ENTRY (priv->entry),
-                                       gtk_printer_option_get_activates_default (source));
-      gtk_box_append (GTK_BOX (widget), priv->entry);
-      g_signal_connect (priv->entry, "changed", G_CALLBACK (entry_changed_cb), widget);
-
-      text = g_strdup_printf ("%s:", source->display_text);
-      priv->label = gtk_label_new_with_mnemonic (text);
-      g_free (text);
-
-      break;
-
-    case GTK_PRINTER_OPTION_TYPE_FILESAVE:
-      priv->button = gtk_button_new ();
-      gtk_box_append (GTK_BOX (widget), priv->button);
-      g_signal_connect (priv->button, "clicked", G_CALLBACK (filesave_choose_cb), widget);
-
-      text = g_strdup_printf ("%s:", source->display_text);
-      priv->label = gtk_label_new_with_mnemonic (text);
-      g_free (text);
-
-      break;
-
-    case GTK_PRINTER_OPTION_TYPE_INFO:
-      priv->info_label = gtk_label_new (NULL);
-      gtk_label_set_selectable (GTK_LABEL (priv->info_label), TRUE);
-      gtk_box_append (GTK_BOX (widget), priv->info_label);
-
-      text = g_strdup_printf ("%s:", source->display_text);
-      priv->label = gtk_label_new_with_mnemonic (text);
-      g_free (text);
-
-      break;
-
-    default:
-      break;
-    }
-
-  priv->image = gtk_image_new_from_icon_name ("dialog-warning");
-  gtk_box_append (GTK_BOX (widget), priv->image);
-}
-
-/*
- * If the filename exceeds FILENAME_LENGTH_MAX, then trim it and replace
- * the first three letters with three dots.
- */
-static char *
-trim_long_filename (const char *filename)
-{
-  const char *home;
-  int len, offset;
-  char *result;
-
-  home = g_get_home_dir ();
-  if (g_str_has_prefix (filename, home))
-    {
-      char *homeless_filename;
-
-      offset = g_utf8_strlen (home, -1);
-      len = g_utf8_strlen (filename, -1);
-      homeless_filename = g_utf8_substring (filename, offset, len);
-      result = g_strconcat ("~", homeless_filename, NULL);
-      g_free (homeless_filename);
-    }
-  else
-    result = g_strdup (filename);
-
-  len = g_utf8_strlen (result, -1);
-  if (len > FILENAME_LENGTH_MAX)
-    {
-      char *suffix;
-
-      suffix = g_utf8_substring (result, len - FILENAME_LENGTH_MAX, len);
-      g_free (result);
-      result = g_strconcat ("...", suffix, NULL);
-      g_free (suffix);
-    }
-
-  return result;
-}
-
-static void
-update_widgets (GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-  GtkPrinterOption *source;
-
-  source = priv->source;
-
-  if (source == NULL)
-    {
-      gtk_widget_set_visible (priv->image, FALSE);
-      return;
-    }
-
-  switch (source->type)
-    {
-    case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
-      if (g_ascii_strcasecmp (source->value, "True") == 0)
-       gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), TRUE);
-      else
-       gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), FALSE);
-      break;
-    case GTK_PRINTER_OPTION_TYPE_PICKONE:
-      combo_box_set (priv->combo, source->value);
-      break;
-    case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
-      alternative_set (priv->box, source->value);
-      break;
-    case GTK_PRINTER_OPTION_TYPE_STRING:
-      gtk_editable_set_text (GTK_EDITABLE (priv->entry), source->value);
-      break;
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
-    case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
-      {
-        GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
-        if (gtk_printer_option_has_choice (source, source->value))
-          combo_box_set (priv->combo, source->value);
-        else
-          gtk_editable_set_text (GTK_EDITABLE (entry), source->value);
-
-        break;
-      }
-    case GTK_PRINTER_OPTION_TYPE_FILESAVE:
-      {
-        char *text;
-        char *filename;
-
-        filename = g_filename_from_uri (source->value, NULL, NULL);
-        if (filename != NULL)
-          {
-            text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
-            if (text != NULL)
-              {
-                char *short_filename;
-
-                short_filename = trim_long_filename (text);
-                gtk_button_set_label (GTK_BUTTON (priv->button), short_filename);
-                g_free (short_filename);
-              }
-
-            g_free (text);
-            g_free (filename);
-          }
-        else
-          gtk_button_set_label (GTK_BUTTON (priv->button), source->value);
-        break;
-      }
-    case GTK_PRINTER_OPTION_TYPE_INFO:
-      gtk_label_set_text (GTK_LABEL (priv->info_label), source->value);
-      break;
-    default:
-      break;
-    }
-
-  gtk_widget_set_visible (priv->image, source->has_conflict);
-}
-
-gboolean
-gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *widget)
-{
-  return widget->priv->label != NULL;
-}
-
-GtkWidget *
-gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget  *widget)
-{
-  return widget->priv->label;
-}
-
-const char *
-gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
-
-  if (priv->source)
-    return priv->source->value;
-
-  return "";
-}
diff --git a/gtk/gtkprinteroptionwidgetprivate.h b/gtk/gtkprinteroptionwidgetprivate.h
deleted file mode 100644 (file)
index b470cfd..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* GtkPrinterOptionWidget 
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include "gtkprinteroptionprivate.h"
-#include "gtkbox.h"
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINTER_OPTION_WIDGET                  (gtk_printer_option_widget_get_type ())
-#define GTK_PRINTER_OPTION_WIDGET(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidget))
-#define GTK_PRINTER_OPTION_WIDGET_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
-#define GTK_IS_PRINTER_OPTION_WIDGET(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET))
-#define GTK_IS_PRINTER_OPTION_WIDGET_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET))
-#define GTK_PRINTER_OPTION_WIDGET_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
-
-
-typedef struct _GtkPrinterOptionWidget         GtkPrinterOptionWidget;
-typedef struct _GtkPrinterOptionWidgetClass    GtkPrinterOptionWidgetClass;
-typedef struct GtkPrinterOptionWidgetPrivate   GtkPrinterOptionWidgetPrivate;
-
-struct _GtkPrinterOptionWidget
-{
-  GtkBox parent_instance;
-
-  GtkPrinterOptionWidgetPrivate *priv;
-};
-
-struct _GtkPrinterOptionWidgetClass
-{
-  GtkBoxClass parent_class;
-
-  void (*changed) (GtkPrinterOptionWidget *widget);
-
-  /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
-};
-
-GDK_AVAILABLE_IN_ALL
-GType       gtk_printer_option_widget_get_type           (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkWidget   *gtk_printer_option_widget_new                (GtkPrinterOption       *source);
-GDK_AVAILABLE_IN_ALL
-void         gtk_printer_option_widget_set_source         (GtkPrinterOptionWidget *setting,
-                                                          GtkPrinterOption       *source);
-GDK_AVAILABLE_IN_ALL
-gboolean     gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *setting);
-GDK_AVAILABLE_IN_ALL
-GtkWidget   *gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *setting);
-GDK_AVAILABLE_IN_ALL
-const char *gtk_printer_option_widget_get_value          (GtkPrinterOptionWidget *setting);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprinterprivate.h b/gtk/gtkprinterprivate.h
deleted file mode 100644 (file)
index 409e66f..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-#include <gtk/gtkunixprint.h>
-#include "gtkprinteroptionsetprivate.h"
-
-G_BEGIN_DECLS
-
-#define GTK_PRINTER_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER, GtkPrinterClass))
-#define GTK_IS_PRINTER_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER))
-#define GTK_PRINTER_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER, GtkPrinterClass))
-
-typedef struct _GtkPrinterClass     GtkPrinterClass;
-typedef struct _GtkPrinterPrivate   GtkPrinterPrivate;
-
-struct _GtkPrinter
-{
-  GObject parent_instance;
-};
-
-struct _GtkPrinterClass
-{
-  GObjectClass parent_class;
-
-  void (*details_acquired) (GtkPrinter *printer,
-                            gboolean    success);
-};
-
-GtkPrinterOptionSet *_gtk_printer_get_options               (GtkPrinter          *printer,
-                                                            GtkPrintSettings    *settings,
-                                                            GtkPageSetup        *page_setup,
-                                                            GtkPrintCapabilities capabilities);
-gboolean             _gtk_printer_mark_conflicts            (GtkPrinter          *printer,
-                                                            GtkPrinterOptionSet *options);
-void                 _gtk_printer_get_settings_from_options (GtkPrinter          *printer,
-                                                            GtkPrinterOptionSet *options,
-                                                            GtkPrintSettings    *settings);
-void                 _gtk_printer_prepare_for_print         (GtkPrinter          *printer,
-                                                            GtkPrintJob         *print_job,
-                                                            GtkPrintSettings    *settings,
-                                                            GtkPageSetup        *page_setup);
-cairo_surface_t *    _gtk_printer_create_cairo_surface      (GtkPrinter          *printer,
-                                                            GtkPrintSettings    *settings,
-                                                            double               width,
-                                                            double               height,
-                                                            GIOChannel          *cache_io);
-GHashTable *         _gtk_printer_get_custom_widgets        (GtkPrinter          *printer);
-
-/* GtkPrintJob private methods: */
-GDK_AVAILABLE_IN_ALL
-void gtk_print_job_set_status (GtkPrintJob   *job,
-                              GtkPrintStatus status);
-
-G_END_DECLS
diff --git a/gtk/gtkprintjob.c b/gtk/gtkprintjob.c
deleted file mode 100644 (file)
index b295d8d..0000000
+++ /dev/null
@@ -1,1001 +0,0 @@
-/* GtkPrintJob
- * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * GtkPrintJob:
- *
- * A `GtkPrintJob` object represents a job that is sent to a printer.
- *
- * You only need to deal directly with print jobs if you use the
- * non-portable [class@Gtk.PrintUnixDialog] API.
- *
- * Use [method@Gtk.PrintJob.get_surface] to obtain the cairo surface
- * onto which the pages must be drawn. Use [method@Gtk.PrintJob.send]
- * to send the finished job to the printer. If you don’t use cairo
- * `GtkPrintJob` also supports printing of manually generated PostScript,
- * via [method@Gtk.PrintJob.set_source_file].
- */
-#include "config.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <glib/gstdio.h>
-#include "gtkprivate.h"
-
-#include "gtkprintjob.h"
-#include "gtkprinter.h"
-#include "gtkprinterprivate.h"
-#include "gtkprintbackendprivate.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-typedef struct _GtkPrintJobClass     GtkPrintJobClass;
-
-struct _GtkPrintJob
-{
-  GObject parent_instance;
-
-  char *title;
-
-  GIOChannel *spool_io;
-  cairo_surface_t *surface;
-
-  GtkPrintStatus status;
-  GtkPrintBackend *backend;
-  GtkPrinter *printer;
-  GtkPrintSettings *settings;
-  GtkPageSetup *page_setup;
-
-  GtkPrintPages print_pages;
-  GtkPageRange *page_ranges;
-  int num_page_ranges;
-  GtkPageSet page_set;
-  int num_copies;
-  double scale;
-  guint number_up;
-  GtkNumberUpLayout number_up_layout;
-
-  guint printer_set           : 1;
-  guint page_setup_set        : 1;
-  guint settings_set          : 1;
-  guint track_print_status    : 1;
-  guint rotate_to_orientation : 1;
-  guint collate               : 1;
-  guint reverse               : 1;
-};
-
-struct _GtkPrintJobClass
-{
-  GObjectClass parent_class;
-
-  void (*status_changed) (GtkPrintJob *job);
-};
-
-static void     gtk_print_job_finalize     (GObject               *object);
-static void     gtk_print_job_set_property (GObject               *object,
-                                           guint                  prop_id,
-                                           const GValue          *value,
-                                           GParamSpec            *pspec);
-static void     gtk_print_job_get_property (GObject               *object,
-                                           guint                  prop_id,
-                                           GValue                *value,
-                                           GParamSpec            *pspec);
-static void     gtk_print_job_constructed  (GObject               *object);
-
-enum {
-  STATUS_CHANGED,
-  LAST_SIGNAL
-};
-
-enum {
-  PROP_0,
-  PROP_TITLE,
-  PROP_PRINTER,
-  PROP_PAGE_SETUP,
-  PROP_SETTINGS,
-  PROP_TRACK_PRINT_STATUS
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
-
-static void
-gtk_print_job_class_init (GtkPrintJobClass *class)
-{
-  GObjectClass *object_class;
-  object_class = (GObjectClass *) class;
-
-  object_class->finalize = gtk_print_job_finalize;
-  object_class->constructed = gtk_print_job_constructed;
-  object_class->set_property = gtk_print_job_set_property;
-  object_class->get_property = gtk_print_job_get_property;
-
-  /**
-   * GtkPrintJob:title: (attributes org.gtk.Property.get=gtk_print_job_get_title)
-   *
-   * The title of the print job.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_TITLE,
-                                   g_param_spec_string ("title", NULL, NULL,
-                                                       NULL,
-                                                       GTK_PARAM_READWRITE |
-                                                       G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrintJob:printer: (attributes org.gtk.Property.get=gtk_print_job_get_printer)
-   *
-   * The printer to send the job to.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_PRINTER,
-                                   g_param_spec_object ("printer", NULL, NULL,
-                                                       GTK_TYPE_PRINTER,
-                                                       GTK_PARAM_READWRITE |
-                                                       G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrintJob:settings: (attributes org.gtk.Property.get=gtk_print_job_get_settings)
-   *
-   * Printer settings.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_SETTINGS,
-                                   g_param_spec_object ("settings", NULL, NULL,
-                                                       GTK_TYPE_PRINT_SETTINGS,
-                                                       GTK_PARAM_READWRITE |
-                                                       G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrintJob:page-setup:
-   *
-   * Page setup.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_PAGE_SETUP,
-                                   g_param_spec_object ("page-setup", NULL, NULL,
-                                                       GTK_TYPE_PAGE_SETUP,
-                                                       GTK_PARAM_READWRITE |
-                                                       G_PARAM_CONSTRUCT_ONLY));
-
-  /**
-   * GtkPrintJob:track-print-status: (attributes org.gtk.Property.get=gtk_print_job_get_track_print_status org.gtk.Property.set=gtk_print_job_set_track_print_status)
-   *
-   * %TRUE if the print job will continue to emit status-changed
-   * signals after the print data has been setn to the printer.
-   */
-  g_object_class_install_property (object_class,
-                                  PROP_TRACK_PRINT_STATUS,
-                                  g_param_spec_boolean ("track-print-status", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintJob::status-changed:
-   * @job: the `GtkPrintJob` object on which the signal was emitted
-   *
-   * Emitted when the status of a job changes.
-   *
-   * The signal handler can use [method@Gtk.PrintJob.get_status]
-   * to obtain the new status.
-   */
-  signals[STATUS_CHANGED] =
-    g_signal_new (I_("status-changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-}
-
-static void
-gtk_print_job_init (GtkPrintJob *job)
-{
-  job->spool_io = NULL;
-
-  job->title = g_strdup ("");
-  job->surface = NULL;
-  job->backend = NULL;
-  job->printer = NULL;
-
-  job->printer_set = FALSE;
-  job->settings_set = FALSE;
-  job->page_setup_set = FALSE;
-  job->status = GTK_PRINT_STATUS_INITIAL;
-  job->track_print_status = FALSE;
-
-  job->print_pages = GTK_PRINT_PAGES_ALL;
-  job->page_ranges = NULL;
-  job->num_page_ranges = 0;
-  job->collate = FALSE;
-  job->reverse = FALSE;
-  job->num_copies = 1;
-  job->scale = 1.0;
-  job->page_set = GTK_PAGE_SET_ALL;
-  job->rotate_to_orientation = FALSE;
-  job->number_up = 1;
-  job->number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-}
-
-
-static void
-gtk_print_job_constructed (GObject *object)
-{
-  GtkPrintJob *job = GTK_PRINT_JOB (object);
-
-  G_OBJECT_CLASS (gtk_print_job_parent_class)->constructed (object);
-
-  g_assert (job->printer_set &&
-           job->settings_set &&
-           job->page_setup_set);
-  
-  _gtk_printer_prepare_for_print (job->printer,
-                                 job,
-                                 job->settings,
-                                 job->page_setup);
-}
-
-
-static void
-gtk_print_job_finalize (GObject *object)
-{
-  GtkPrintJob *job = GTK_PRINT_JOB (object);
-
-  if (job->surface)
-    cairo_surface_destroy (job->surface);
-
-  if (job->backend)
-    g_object_unref (job->backend);
-
-  if (job->spool_io != NULL)
-    {
-      g_io_channel_unref (job->spool_io);
-      job->spool_io = NULL;
-    }
-
-  if (job->printer)
-    g_object_unref (job->printer);
-
-  if (job->settings)
-    g_object_unref (job->settings);
-
-  if (job->page_setup)
-    g_object_unref (job->page_setup);
-
-  g_free (job->page_ranges);
-  job->page_ranges = NULL;
-
-  g_free (job->title);
-  job->title = NULL;
-
-  G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
-}
-
-/**
- * gtk_print_job_new:
- * @title: the job title
- * @printer: a `GtkPrinter`
- * @settings: a `GtkPrintSettings`
- * @page_setup: a `GtkPageSetup`
- *
- * Creates a new `GtkPrintJob`.
- *
- * Returns: a new `GtkPrintJob`
- */
-GtkPrintJob *
-gtk_print_job_new (const char       *title,
-                  GtkPrinter       *printer,
-                  GtkPrintSettings *settings,
-                  GtkPageSetup     *page_setup)
-{
-  GObject *result;
-  result = g_object_new (GTK_TYPE_PRINT_JOB,
-                         "title", title,
-                        "printer", printer,
-                        "settings", settings,
-                        "page-setup", page_setup,
-                        NULL);
-  return (GtkPrintJob *) result;
-}
-
-/**
- * gtk_print_job_get_settings: (attributes org.gtk.Method.get_property=settings)
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrintSettings` of the print job.
- *
- * Returns: (transfer none): the settings of @job
- */
-GtkPrintSettings *
-gtk_print_job_get_settings (GtkPrintJob *job)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-  
-  return job->settings;
-}
-
-/**
- * gtk_print_job_get_printer: (attributes org.gtk.Method.get_property=printer)
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrinter` of the print job.
- *
- * Returns: (transfer none): the printer of @job
- */
-GtkPrinter *
-gtk_print_job_get_printer (GtkPrintJob *job)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-  
-  return job->printer;
-}
-
-/**
- * gtk_print_job_get_title: (attributes org.gtk.Method.get_property=title)
- * @job: a `GtkPrintJob`
- *
- * Gets the job title.
- *
- * Returns: the title of @job
- */
-const char *
-gtk_print_job_get_title (GtkPrintJob *job)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-  
-  return job->title;
-}
-
-/**
- * gtk_print_job_get_status:
- * @job: a `GtkPrintJob`
- *
- * Gets the status of the print job.
- *
- * Returns: the status of @job
- */
-GtkPrintStatus
-gtk_print_job_get_status (GtkPrintJob *job)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
-  
-  return job->status;
-}
-
-void
-gtk_print_job_set_status (GtkPrintJob   *job,
-                         GtkPrintStatus status)
-{
-  g_return_if_fail (GTK_IS_PRINT_JOB (job));
-
-  if (job->status == status)
-    return;
-
-  job->status = status;
-  g_signal_emit (job, signals[STATUS_CHANGED], 0);
-}
-
-/**
- * gtk_print_job_set_source_file:
- * @job: a `GtkPrintJob`
- * @filename: (type filename): the file to be printed
- * @error: return location for errors
- *
- * Make the `GtkPrintJob` send an existing document to the
- * printing system.
- *
- * The file can be in any format understood by the platforms
- * printing system (typically PostScript, but on many platforms
- * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
- * [method@Gtk.Printer.accepts_ps].
- *
- * Returns: %FALSE if an error occurred
- */
-gboolean
-gtk_print_job_set_source_file (GtkPrintJob *job,
-                              const char *filename,
-                              GError     **error)
-{
-  GError *tmp_error;
-
-  tmp_error = NULL;
-
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
-
-  if (job->spool_io != NULL)
-    g_io_channel_unref (job->spool_io);
-
-  job->spool_io = g_io_channel_new_file (filename, "r", &tmp_error);
-
-  if (tmp_error == NULL)
-    g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
-
-  if (tmp_error != NULL)
-    {
-      g_propagate_error (error, tmp_error);
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-/**
- * gtk_print_job_set_source_fd:
- * @job: a `GtkPrintJob`
- * @fd: a file descriptor
- * @error: return location for errors
- *
- * Make the `GtkPrintJob` send an existing document to the
- * printing system.
- *
- * The file can be in any format understood by the platforms
- * printing system (typically PostScript, but on many platforms
- * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
- * [method@Gtk.Printer.accepts_ps].
- *
- * This is similar to [method@Gtk.PrintJob.set_source_file],
- * but takes expects an open file descriptor for the file,
- * instead of a filename.
- *
- * Returns: %FALSE if an error occurred
- */
-gboolean
-gtk_print_job_set_source_fd (GtkPrintJob  *job,
-                             int           fd,
-                             GError      **error)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
-  g_return_val_if_fail (fd >= 0, FALSE);
-
-  if (job->spool_io != NULL)
-    g_io_channel_unref (job->spool_io);
-
-  job->spool_io = g_io_channel_unix_new (fd);
-  if (g_io_channel_set_encoding (job->spool_io, NULL, error) != G_IO_STATUS_NORMAL)
-    return FALSE;
-
-  return TRUE;
-}
-
-/**
- * gtk_print_job_get_surface:
- * @job: a `GtkPrintJob`
- * @error: (nullable): return location for errors
- *
- * Gets a cairo surface onto which the pages of
- * the print job should be rendered.
- *
- * Returns: (transfer none): the cairo surface of @job
- */
-cairo_surface_t *
-gtk_print_job_get_surface (GtkPrintJob  *job,
-                          GError      **error)
-{
-  char *filename = NULL;
-  double width, height;
-  GtkPaperSize *paper_size;
-  int fd;
-  GError *tmp_error;
-
-  tmp_error = NULL;
-
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
-
-  if (job->surface)
-    return job->surface;
-  g_return_val_if_fail (job->spool_io == NULL, NULL);
-  fd = g_file_open_tmp ("gtkprint_XXXXXX", 
-                        &filename, 
-                        &tmp_error);
-  if (fd == -1)
-    {
-      g_free (filename);
-      g_propagate_error (error, tmp_error);
-      return NULL;
-    }
-
-  fchmod (fd, S_IRUSR | S_IWUSR);
-  
-#ifdef G_ENABLE_DEBUG
-  /* If we are debugging printing don't delete the tmp files */
-  if (GTK_DEBUG_CHECK (PRINTING)) ;
-  else
-#endif /* G_ENABLE_DEBUG */
-  g_unlink (filename);
-  g_free (filename);
-
-  paper_size = gtk_page_setup_get_paper_size (job->page_setup);
-  width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
-  height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-  job->spool_io = g_io_channel_unix_new (fd);
-  g_io_channel_set_close_on_unref (job->spool_io, TRUE);
-  g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
-  
-  if (tmp_error != NULL)
-    {
-      g_io_channel_unref (job->spool_io);
-      job->spool_io = NULL;
-      g_propagate_error (error, tmp_error);
-      return NULL;
-    }
-
-  job->surface = _gtk_printer_create_cairo_surface (job->printer,
-                                                    job->settings,
-                                                    width, height,
-                                                    job->spool_io);
-  
-  return job->surface;
-}
-
-/**
- * gtk_print_job_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
- * @job: a `GtkPrintJob`
- * @track_status: %TRUE to track status after printing
- *
- * If track_status is %TRUE, the print job will try to continue report
- * on the status of the print job in the printer queues and printer.
- *
- * This can allow your application to show things like “out of paper”
- * issues, and when the print job actually reaches the printer.
- *
- * This function is often implemented using some form of polling,
- * so it should not be enabled unless needed.
- */
-void
-gtk_print_job_set_track_print_status (GtkPrintJob *job,
-                                     gboolean     track_status)
-{
-  g_return_if_fail (GTK_IS_PRINT_JOB (job));
-
-  track_status = track_status != FALSE;
-
-  if (job->track_print_status != track_status)
-    {
-      job->track_print_status = track_status;
-      
-      g_object_notify (G_OBJECT (job), "track-print-status");
-    }
-}
-
-/**
- * gtk_print_job_get_track_print_status: (attributes org.gtk.Method.get_property=track-print-status)
- * @job: a `GtkPrintJob`
- *
- * Returns whether jobs will be tracked after printing.
- *
- * For details, see [method@Gtk.PrintJob.set_track_print_status].
- *
- * Returns: %TRUE if print job status will be reported after printing
- */
-gboolean
-gtk_print_job_get_track_print_status (GtkPrintJob *job)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
-  
-  return job->track_print_status;
-}
-
-static void
-gtk_print_job_set_property (GObject      *object,
-                           guint         prop_id,
-                           const GValue *value,
-                            GParamSpec   *pspec)
-
-{
-  GtkPrintJob *job = GTK_PRINT_JOB (object);
-  GtkPrintSettings *settings;
-
-  switch (prop_id)
-    {
-    case PROP_TITLE:
-      g_free (job->title);
-      job->title = g_value_dup_string (value);
-      break;
-    
-    case PROP_PRINTER:
-      job->printer = GTK_PRINTER (g_value_dup_object (value));
-      job->printer_set = TRUE;
-      job->backend = g_object_ref (gtk_printer_get_backend (job->printer));
-      break;
-
-    case PROP_PAGE_SETUP:
-      job->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
-      job->page_setup_set = TRUE;
-      break;
-      
-    case PROP_SETTINGS:
-      /* We save a copy of the settings since we modify
-       * if when preparing the printer job. */
-      settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
-      job->settings = gtk_print_settings_copy (settings);
-      job->settings_set = TRUE;
-      break;
-
-    case PROP_TRACK_PRINT_STATUS:
-      gtk_print_job_set_track_print_status (job, g_value_get_boolean (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_print_job_get_property (GObject    *object,
-                           guint       prop_id,
-                           GValue     *value,
-                           GParamSpec *pspec)
-{
-  GtkPrintJob *job = GTK_PRINT_JOB (object);
-
-  switch (prop_id)
-    {
-    case PROP_TITLE:
-      g_value_set_string (value, job->title);
-      break;
-    case PROP_PRINTER:
-      g_value_set_object (value, job->printer);
-      break;
-    case PROP_SETTINGS:
-      g_value_set_object (value, job->settings);
-      break;
-    case PROP_PAGE_SETUP:
-      g_value_set_object (value, job->page_setup);
-      break;
-    case PROP_TRACK_PRINT_STATUS:
-      g_value_set_boolean (value, job->track_print_status);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-/**
- * gtk_print_job_send:
- * @job: a `GtkPrintJob`
- * @callback: function to call when the job completes or an error occurs
- * @user_data: (closure): user data that gets passed to @callback
- * @dnotify: destroy notify for @user_data
- *
- * Sends the print job off to the printer.
- */
-void
-gtk_print_job_send (GtkPrintJob             *job,
-                    GtkPrintJobCompleteFunc  callback,
-                    gpointer                 user_data,
-                   GDestroyNotify           dnotify)
-{
-  g_return_if_fail (GTK_IS_PRINT_JOB (job));
-  g_return_if_fail (job->spool_io != NULL);
-  
-  gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
-  
-  g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
-  
-  gtk_print_backend_print_stream (job->backend, job,
-                                 job->spool_io,
-                                  callback, user_data, dnotify);
-}
-
-/**
- * gtk_print_job_get_pages:
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPrintPages` setting for this job.
- *
- * Returns: the `GtkPrintPages` setting
- */
-GtkPrintPages
-gtk_print_job_get_pages (GtkPrintJob *job)
-{
-  return job->print_pages;
-}
-
-/**
- * gtk_print_job_set_pages:
- * @job: a `GtkPrintJob`
- * @pages: the `GtkPrintPages` setting
- *
- * Sets the `GtkPrintPages` setting for this job.
- */
-void
-gtk_print_job_set_pages (GtkPrintJob   *job,
-                         GtkPrintPages  pages)
-{
-  job->print_pages = pages;
-}
-
-/**
- * gtk_print_job_get_page_ranges:
- * @job: a `GtkPrintJob`
- * @n_ranges: (out): return location for the number of ranges
- *
- * Gets the page ranges for this job.
- *
- * Returns: (array length=n_ranges) (transfer none): a pointer to an
- *   array of `GtkPageRange` structs
- */
-GtkPageRange *
-gtk_print_job_get_page_ranges (GtkPrintJob *job,
-                               int         *n_ranges)
-{
-  *n_ranges = job->num_page_ranges;
-  return job->page_ranges;
-}
-
-/**
- * gtk_print_job_set_page_ranges:
- * @job: a `GtkPrintJob`
- * @ranges: (array length=n_ranges) (transfer full): pointer to an array of
- *    `GtkPageRange` structs
- * @n_ranges: the length of the @ranges array
- *
- * Sets the page ranges for this job.
- */
-void
-gtk_print_job_set_page_ranges (GtkPrintJob  *job,
-                               GtkPageRange *ranges,
-                               int           n_ranges)
-{
-  g_free (job->page_ranges);
-  job->page_ranges = ranges;
-  job->num_page_ranges = n_ranges;
-}
-
-/**
- * gtk_print_job_get_page_set:
- * @job: a `GtkPrintJob`
- *
- * Gets the `GtkPageSet` setting for this job.
- *
- * Returns: the `GtkPageSet` setting
- */
-GtkPageSet
-gtk_print_job_get_page_set (GtkPrintJob *job)
-{
-  return job->page_set;
-}
-
-/**
- * gtk_print_job_set_page_set:
- * @job: a `GtkPrintJob`
- * @page_set: a `GtkPageSet` setting
- *
- * Sets the `GtkPageSet` setting for this job.
- */
-void
-gtk_print_job_set_page_set (GtkPrintJob *job,
-                            GtkPageSet   page_set)
-{
-  job->page_set = page_set;
-}
-
-/**
- * gtk_print_job_get_num_copies:
- * @job: a `GtkPrintJob`
- *
- * Gets the number of copies of this job.
- *
- * Returns: the number of copies
- */
-int
-gtk_print_job_get_num_copies (GtkPrintJob *job)
-{
-  return job->num_copies;
-}
-
-/**
- * gtk_print_job_set_num_copies:
- * @job: a `GtkPrintJob`
- * @num_copies: the number of copies
- *
- * Sets the number of copies for this job.
- */
-void
-gtk_print_job_set_num_copies (GtkPrintJob *job,
-                              int          num_copies)
-{
-  job->num_copies = num_copies;
-}
-
-/**
- * gtk_print_job_get_scale:
- * @job: a `GtkPrintJob`
- *
- * Gets the scale for this job.
- *
- * Returns: the scale
- */
-double
-gtk_print_job_get_scale (GtkPrintJob *job)
-
-{
-  return job->scale;
-}
-
-/**
- * gtk_print_job_set_scale:
- * @job: a `GtkPrintJob`
- * @scale: the scale
- *
- * Sets the scale for this job.
- *
- * 1.0 means unscaled.
- */
-void
-gtk_print_job_set_scale (GtkPrintJob *job,
-                         double       scale)
-{
-  job->scale = scale;
-}
-
-/**
- * gtk_print_job_get_n_up:
- * @job: a `GtkPrintJob`
- *
- * Gets the n-up setting for this job.
- *
- * Returns: the n-up setting
- */
-guint
-gtk_print_job_get_n_up (GtkPrintJob *job)
-{
-  return job->number_up;
-}
-
-/**
- * gtk_print_job_set_n_up:
- * @job: a `GtkPrintJob`
- * @n_up: the n-up value
- *
- * Sets the n-up setting for this job.
- */
-void
-gtk_print_job_set_n_up (GtkPrintJob *job,
-                        guint        n_up)
-{
-  job->number_up = n_up;
-}
-
-/**
- * gtk_print_job_get_n_up_layout:
- * @job: a `GtkPrintJob`
- *
- * Gets the n-up layout setting for this job.
- *
- * Returns: the n-up layout
- */
-GtkNumberUpLayout
-gtk_print_job_get_n_up_layout (GtkPrintJob *job)
-{
-  return job->number_up_layout;
-}
-
-/**
- * gtk_print_job_set_n_up_layout:
- * @job: a `GtkPrintJob`
- * @layout: the n-up layout setting
- *
- * Sets the n-up layout setting for this job.
- */
-void
-gtk_print_job_set_n_up_layout (GtkPrintJob       *job,
-                               GtkNumberUpLayout  layout)
-{
-  job->number_up_layout = layout;
-}
-
-/**
- * gtk_print_job_get_rotate:
- * @job: a `GtkPrintJob`
- *
- * Gets whether the job is printed rotated.
- *
- * Returns: whether the job is printed rotated
- */
-gboolean
-gtk_print_job_get_rotate (GtkPrintJob *job)
-{
-  return job->rotate_to_orientation;
-}
-
-/**
- * gtk_print_job_set_rotate:
- * @job: a `GtkPrintJob`
- * @rotate: whether to print rotated
- *
- * Sets whether this job is printed rotated.
- */
-void
-gtk_print_job_set_rotate (GtkPrintJob *job,
-                          gboolean     rotate)
-{
-  job->rotate_to_orientation = rotate;
-}
-
-/**
- * gtk_print_job_get_collate:
- * @job: a `GtkPrintJob`
- *
- * Gets whether this job is printed collated.
- *
- * Returns: whether the job is printed collated
- */
-gboolean
-gtk_print_job_get_collate (GtkPrintJob *job)
-{
-  return job->collate;
-}
-
-/**
- * gtk_print_job_set_collate:
- * @job: a `GtkPrintJob`
- * @collate: whether the job is printed collated
- *
- * Sets whether this job is printed collated.
- */
-void
-gtk_print_job_set_collate (GtkPrintJob *job,
-                           gboolean     collate)
-{
-  job->collate = collate;
-}
-
-/**
- * gtk_print_job_get_reverse:
- * @job: a `GtkPrintJob`
- *
- * Gets whether this job is printed reversed.
- *
- * Returns: whether the job is printed reversed.
- */
-gboolean
-gtk_print_job_get_reverse (GtkPrintJob *job)
-{
-  return job->reverse;
-}
-
-/**
- * gtk_print_job_set_reverse:
- * @job: a `GtkPrintJob`
- * @reverse: whether the job is printed reversed
- *
- * Sets whether this job is printed reversed.
- */
-void
-gtk_print_job_set_reverse (GtkPrintJob *job,
-                           gboolean     reverse)
-{
-  job->reverse = reverse;
-}
diff --git a/gtk/gtkprintjob.h b/gtk/gtkprintjob.h
deleted file mode 100644 (file)
index b1e4563..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <cairo.h>
-
-#include <gtk/gtk.h>
-#include <gtk/gtkprinter.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_JOB                  (gtk_print_job_get_type ())
-#define GTK_PRINT_JOB(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_JOB, GtkPrintJob))
-#define GTK_IS_PRINT_JOB(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_JOB))
-
-typedef struct _GtkPrintJob          GtkPrintJob;
-
-/**
- * GtkPrintJobCompleteFunc:
- * @print_job: the `GtkPrintJob`
- * @user_data: user data that has been passed to gtk_print_job_send()
- * @error: a `GError` that contains error information if the sending
- *   of the print job failed, otherwise %NULL
- *
- * The type of callback that is passed to gtk_print_job_send().
- *
- * It is called when the print job has been completely sent.
- */
-typedef void (*GtkPrintJobCompleteFunc) (GtkPrintJob  *print_job,
-                                         gpointer      user_data,
-                                         const GError *error);
-
-
-GDK_AVAILABLE_IN_ALL
-GType                    gtk_print_job_get_type               (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkPrintJob             *gtk_print_job_new                    (const char               *title,
-                                                              GtkPrinter               *printer,
-                                                              GtkPrintSettings         *settings,
-                                                              GtkPageSetup             *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings        *gtk_print_job_get_settings           (GtkPrintJob              *job);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter              *gtk_print_job_get_printer            (GtkPrintJob              *job);
-GDK_AVAILABLE_IN_ALL
-const char *            gtk_print_job_get_title              (GtkPrintJob              *job);
-GDK_AVAILABLE_IN_ALL
-GtkPrintStatus           gtk_print_job_get_status             (GtkPrintJob              *job);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_print_job_set_source_file        (GtkPrintJob              *job,
-                                                              const char               *filename,
-                                                              GError                  **error);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_print_job_set_source_fd          (GtkPrintJob              *job,
-                                                              int                       fd,
-                                                              GError                  **error);
-GDK_AVAILABLE_IN_ALL
-cairo_surface_t         *gtk_print_job_get_surface            (GtkPrintJob              *job,
-                                                              GError                  **error);
-GDK_AVAILABLE_IN_ALL
-void                     gtk_print_job_set_track_print_status (GtkPrintJob              *job,
-                                                              gboolean                  track_status);
-GDK_AVAILABLE_IN_ALL
-gboolean                 gtk_print_job_get_track_print_status (GtkPrintJob              *job);
-GDK_AVAILABLE_IN_ALL
-void                     gtk_print_job_send                   (GtkPrintJob              *job,
-                                                              GtkPrintJobCompleteFunc   callback,
-                                                              gpointer                  user_data,
-                                                              GDestroyNotify            dnotify);
-
-GDK_AVAILABLE_IN_ALL
-GtkPrintPages     gtk_print_job_get_pages       (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_pages       (GtkPrintJob       *job,
-                                                 GtkPrintPages      pages);
-GDK_AVAILABLE_IN_ALL
-GtkPageRange *    gtk_print_job_get_page_ranges (GtkPrintJob       *job,
-                                                 int               *n_ranges);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_page_ranges (GtkPrintJob       *job,
-                                                 GtkPageRange      *ranges,
-                                                 int                n_ranges);
-GDK_AVAILABLE_IN_ALL
-GtkPageSet        gtk_print_job_get_page_set    (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_page_set    (GtkPrintJob       *job,
-                                                 GtkPageSet         page_set);
-GDK_AVAILABLE_IN_ALL
-int               gtk_print_job_get_num_copies  (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_num_copies  (GtkPrintJob       *job,
-                                                 int                num_copies);
-GDK_AVAILABLE_IN_ALL
-double            gtk_print_job_get_scale       (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_scale       (GtkPrintJob       *job,
-                                                 double             scale);
-GDK_AVAILABLE_IN_ALL
-guint             gtk_print_job_get_n_up        (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_n_up        (GtkPrintJob       *job,
-                                                 guint              n_up);
-GDK_AVAILABLE_IN_ALL
-GtkNumberUpLayout gtk_print_job_get_n_up_layout (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_n_up_layout (GtkPrintJob       *job,
-                                                 GtkNumberUpLayout  layout);
-GDK_AVAILABLE_IN_ALL
-gboolean          gtk_print_job_get_rotate      (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_rotate      (GtkPrintJob       *job,
-                                                 gboolean           rotate);
-GDK_AVAILABLE_IN_ALL
-gboolean          gtk_print_job_get_collate     (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_collate     (GtkPrintJob       *job,
-                                                 gboolean           collate);
-GDK_AVAILABLE_IN_ALL
-gboolean          gtk_print_job_get_reverse     (GtkPrintJob       *job);
-GDK_AVAILABLE_IN_ALL
-void              gtk_print_job_set_reverse     (GtkPrintJob       *job,
-                                                 gboolean           reverse);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintJob, g_object_unref)
-
-G_END_DECLS
-
diff --git a/gtk/gtkprintoperation-portal.c b/gtk/gtkprintoperation-portal.c
deleted file mode 100644 (file)
index 4f4c4cc..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <cairo-pdf.h>
-#include <cairo-ps.h>
-
-#include <gio/gunixfdlist.h>
-
-#include "gtkprintoperation-private.h"
-#include "gtkprintoperation-portal.h"
-#include "print/gtkprintsettings.h"
-#include "print/gtkpagesetup.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkfilelauncher.h"
-#include <glib/gi18n-lib.h>
-#include "gtkwindowprivate.h"
-#include "gtkprivate.h"
-
-
-typedef struct {
-  GtkPrintOperation *op;
-  GDBusProxy *proxy;
-  guint response_signal_id;
-  gboolean do_print;
-  GtkPrintOperationResult result;
-  GtkPrintOperationPrintFunc print_cb;
-  GtkWindow *parent;
-  char *handle;
-  GMainLoop *loop;
-  guint32 token;
-  GDestroyNotify destroy;
-  GVariant *settings;
-  GVariant *setup;
-  GVariant *options;
-  char *prepare_print_handle;
-} PortalData;
-
-static void
-portal_data_free (gpointer data)
-{
-  PortalData *portal = data;
-
-  if (portal->parent && portal->handle)
-    gtk_window_unexport_handle (portal->parent, portal->handle);
-  g_free (portal->handle);
-  g_object_unref (portal->op);
-  g_object_unref (portal->proxy);
-  if (portal->loop)
-    g_main_loop_unref (portal->loop);
-  if (portal->settings)
-    g_variant_unref (portal->settings);
-  if (portal->setup)
-    g_variant_unref (portal->setup);
-  if (portal->options)
-    g_variant_unref (portal->options);
-  g_free (portal->prepare_print_handle);
-  g_free (portal);
-}
-
-typedef struct {
-  GDBusProxy *proxy;
-  GtkPrintJob *job;
-  guint32 token;
-  cairo_surface_t *surface;
-  GMainLoop *loop;
-  gboolean file_written;
-} GtkPrintOperationPortal;
-
-static void
-op_portal_free (GtkPrintOperationPortal *op_portal)
-{
-  g_clear_object (&op_portal->proxy);
-  g_clear_object (&op_portal->job);
-  if (op_portal->loop)
-    g_main_loop_unref (op_portal->loop);
-  g_free (op_portal);
-}
-
-static void
-portal_start_page (GtkPrintOperation *op,
-                   GtkPrintContext   *print_context,
-                   GtkPageSetup      *page_setup)
-{
-  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
-  GtkPaperSize *paper_size;
-  cairo_surface_type_t type;
-  double w, h;
-
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-
-  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
-  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
-  type = cairo_surface_get_type (op_portal->surface);
-
-  if ((op->priv->manual_number_up < 2) ||
-      (op->priv->page_position % op->priv->manual_number_up == 0))
-    {
-      if (type == CAIRO_SURFACE_TYPE_PS)
-        {
-          cairo_ps_surface_set_size (op_portal->surface, w, h);
-          cairo_ps_surface_dsc_begin_page_setup (op_portal->surface);
-          switch (gtk_page_setup_get_orientation (page_setup))
-            {
-              case GTK_PAGE_ORIENTATION_PORTRAIT:
-              case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-                cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Portrait");
-                break;
-
-              case GTK_PAGE_ORIENTATION_LANDSCAPE:
-              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-                cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape");
-                break;
-
-              default:
-                break;
-            }
-         }
-      else if (type == CAIRO_SURFACE_TYPE_PDF)
-        {
-          if (!op->priv->manual_orientation)
-            {
-              w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
-              h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
-            }
-          cairo_pdf_surface_set_size (op_portal->surface, w, h);
-        }
-    }
-}
-
-static void
-portal_end_page (GtkPrintOperation *op,
-                 GtkPrintContext   *print_context)
-{
-  cairo_t *cr;
-
-  cr = gtk_print_context_get_cairo_context (print_context);
-
-  if ((op->priv->manual_number_up < 2) ||
-      ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
-      (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
-    cairo_show_page (cr);
-}
-
-static void
-print_file_done (GObject *source,
-                 GAsyncResult *result,
-                 gpointer data)
-{
-  GtkPrintOperation *op = data;
-  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
-  GError *error = NULL;
-  GVariant *ret;
-
-  ret = g_dbus_proxy_call_finish (op_portal->proxy,
-                                  result,
-                                  &error);
-  if (ret == NULL)
-    {
-      if (op->priv->error == NULL)
-        op->priv->error = g_error_copy (error);
-      g_warning ("Print file failed: %s", error->message);
-      g_error_free (error);
-    }
-  else
-    g_variant_unref (ret);
-
-  if (op_portal->loop)
-    g_main_loop_quit (op_portal->loop);
-
-  g_object_unref (op);
-}
-
-static void
-portal_job_complete (GtkPrintJob  *job,
-                     gpointer      data,
-                     const GError *error)
-{
-  GtkPrintOperation *op = data;
-  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
-  GtkPrintSettings *settings;
-  const char *uri;
-  char *filename;
-  int fd, idx;
-  GVariantBuilder opt_builder;
-  GUnixFDList *fd_list;
-
-  if (error != NULL && op->priv->error == NULL)
-    {
-      g_warning ("Print job failed: %s", error->message);
-      op->priv->error = g_error_copy (error);
-      return;
-    }
-
-  op_portal->file_written = TRUE;
-
-  settings = gtk_print_job_get_settings (job);
-  uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
-  filename = g_filename_from_uri (uri, NULL, NULL);
-
-  fd = open (filename, O_RDONLY|O_CLOEXEC);
-  fd_list = g_unix_fd_list_new ();
-  idx = g_unix_fd_list_append (fd_list, fd, NULL);
-  close (fd);
-
-  g_free (filename);
-
-  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&opt_builder, "{sv}",  "token", g_variant_new_uint32 (op_portal->token));
-
-  g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
-                                       "Print",
-                                       g_variant_new ("(ssh@a{sv})",
-                                                      "", /* window */
-                                                      _("Print"), /* title */
-                                                      idx,
-                                                      g_variant_builder_end (&opt_builder)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       fd_list,
-                                       NULL,
-                                       print_file_done,
-                                       op);
-  g_object_unref (fd_list);
-}
-
-static void
-portal_end_run (GtkPrintOperation *op,
-                gboolean           wait,
-                gboolean           cancelled)
-{
-  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
-
-  cairo_surface_finish (op_portal->surface);
-
-  if (cancelled)
-    return;
-
-  if (wait)
-    op_portal->loop = g_main_loop_new (NULL, FALSE);
-
-  /* TODO: Check for error */
-  if (op_portal->job != NULL)
-    {
-      g_object_ref (op);
-      gtk_print_job_send (op_portal->job, portal_job_complete, op, NULL);
-    }
-
-  if (wait)
-    {
-      g_object_ref (op);
-      if (!op_portal->file_written)
-        g_main_loop_run (op_portal->loop);
-      g_object_unref (op);
-    }
-}
-
-static void
-finish_print (PortalData        *portal,
-              GtkPrinter        *printer,
-              GtkPageSetup      *page_setup,
-              GtkPrintSettings  *settings)
-{
-  GtkPrintOperation *op = portal->op;
-  GtkPrintOperationPrivate *priv = op->priv;
-  GtkPrintJob *job;
-  GtkPrintOperationPortal *op_portal;
-  cairo_t *cr;
-
-  if (portal->do_print)
-    {
-      gtk_print_operation_set_print_settings (op, settings);
-      priv->print_context = _gtk_print_context_new (op);
-
-      _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
-
-      gtk_print_operation_set_default_page_setup (op, page_setup);
-      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-
-      op_portal = g_new0 (GtkPrintOperationPortal, 1);
-      priv->platform_data = op_portal;
-      priv->free_platform_data = (GDestroyNotify) op_portal_free;
-
-      priv->start_page = portal_start_page;
-      priv->end_page = portal_end_page;
-      priv->end_run = portal_end_run;
-
-      job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
-      op_portal->job = job;
-
-      op_portal->proxy = g_object_ref (portal->proxy);
-      op_portal->token = portal->token;
-
-      op_portal->surface = gtk_print_job_get_surface (job, &priv->error);
-      if (op_portal->surface == NULL)
-        {
-          portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
-          portal->do_print = FALSE;
-          goto out;
-        }
-
-      cr = cairo_create (op_portal->surface);
-      gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
-      cairo_destroy (cr);
-
-      priv->print_pages = gtk_print_job_get_pages (job);
-      priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
-      priv->manual_num_copies = gtk_print_job_get_num_copies (job);
-      priv->manual_collation = gtk_print_job_get_collate (job);
-      priv->manual_reverse = gtk_print_job_get_reverse (job);
-      priv->manual_page_set = gtk_print_job_get_page_set (job);
-      priv->manual_scale = gtk_print_job_get_scale (job);
-      priv->manual_orientation = gtk_print_job_get_rotate (job);
-      priv->manual_number_up = gtk_print_job_get_n_up (job);
-      priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
-    }
-
-out:
-  if (portal->print_cb)
-    portal->print_cb (op, portal->parent, portal->do_print, portal->result);
-
-  if (portal->destroy)
-    portal->destroy (portal);
-}
-
-static GtkPrinter *
-find_file_printer (void)
-{
-  GList *backends, *l, *printers;
-  GtkPrinter *printer;
-
-  printer = NULL;
-
-  backends = gtk_print_backend_load_modules ();
-  for (l = backends; l; l = l->next)
-    {
-      GtkPrintBackend *backend = l->data;
-      if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
-        {
-          printers = gtk_print_backend_get_printer_list (backend);
-          printer = printers->data;
-          g_list_free (printers);
-          break;
-        }
-    }
-  g_list_free (backends);
-
-  return printer;
-}
-
-static void
-prepare_print_response (GDBusConnection *connection,
-                        const char      *sender_name,
-                        const char      *object_path,
-                        const char      *interface_name,
-                        const char      *signal_name,
-                        GVariant        *parameters,
-                        gpointer         data)
-{
-  PortalData *portal = data;
-  guint32 response;
-  GVariant *options = NULL;
-
-  if (portal->response_signal_id != 0)
-    {
-      g_dbus_connection_signal_unsubscribe (connection,
-                                            portal->response_signal_id);
-      portal->response_signal_id = 0;
-    }
-
-  g_variant_get (parameters, "(u@a{sv})", &response, &options);
-
-  portal->do_print = (response == 0);
-
-  if (portal->do_print)
-    {
-      GVariant *v;
-      GtkPrintSettings *settings;
-      GtkPageSetup *page_setup;
-      GtkPrinter *printer;
-      char *filename;
-      char *uri;
-      int fd;
-
-      portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
-      v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
-      settings = gtk_print_settings_new_from_gvariant (v);
-      g_variant_unref (v);
-
-      v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT);
-      page_setup = gtk_page_setup_new_from_gvariant (v);
-      g_variant_unref (v);
-
-      g_variant_lookup (options, "token", "u", &portal->token);
-
-      printer = find_file_printer ();
-
-      fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
-      uri = g_filename_to_uri (filename, NULL, NULL);
-      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
-      g_free (uri);
-      close (fd);
-
-      finish_print (portal, printer, page_setup, settings);
-      g_free (filename);
-    }
-  else
-    {
-      portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-
-      if (portal->print_cb)
-        portal->print_cb (portal->op, portal->parent, portal->do_print, portal->result);
-
-      if (portal->destroy)
-        portal->destroy (portal);
-    }
-
-  if (options)
-    g_variant_unref (options);
-
-  if (portal->loop)
-    g_main_loop_quit (portal->loop);
-}
-
-static void
-prepare_print_called (GObject      *source,
-                      GAsyncResult *result,
-                      gpointer      data)
-{
-  PortalData *portal = data;
-  GError *error = NULL;
-  const char *handle = NULL;
-  GVariant *ret;
-
-  ret = g_dbus_proxy_call_finish (portal->proxy, result, &error);
-  if (ret == NULL)
-    {
-      if (portal->op->priv->error == NULL)
-        portal->op->priv->error = g_error_copy (error);
-      g_error_free (error);
-      if (portal->loop)
-        g_main_loop_quit (portal->loop);
-      return;
-    }
-  else
-    g_variant_get (ret, "(&o)", &handle);
-
-  if (strcmp (portal->prepare_print_handle, handle) != 0)
-    {
-      g_free (portal->prepare_print_handle);
-      portal->prepare_print_handle = g_strdup (handle);
-      g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
-                                            portal->response_signal_id);
-      portal->response_signal_id =
-        g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
-                                            PORTAL_BUS_NAME,
-                                            PORTAL_REQUEST_INTERFACE,
-                                            "Response",
-                                            handle,
-                                            NULL,
-                                            G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
-                                            prepare_print_response,
-                                            portal, NULL);
-     }
-
-  g_variant_unref (ret);
-}
-
-static PortalData *
-create_portal_data (GtkPrintOperation          *op,
-                    GtkWindow                  *parent,
-                    GtkPrintOperationPrintFunc  print_cb)
-{
-  GDBusProxy *proxy;
-  PortalData *portal;
-  guint signal_id;
-  GError *error = NULL;
-
-  signal_id = g_signal_lookup ("create-custom-widget", GTK_TYPE_PRINT_OPERATION);
-  if (g_signal_has_handler_pending (op, signal_id, 0, TRUE))
-    g_warning ("GtkPrintOperation::create-custom-widget not supported with portal");
-
-  proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
-                                         G_DBUS_PROXY_FLAGS_NONE,
-                                         NULL,
-                                         PORTAL_BUS_NAME,
-                                         PORTAL_OBJECT_PATH,
-                                         PORTAL_PRINT_INTERFACE,
-                                         NULL,
-                                         &error);
-
-  if (proxy == NULL)
-    {
-      if (op->priv->error == NULL)
-        op->priv->error = g_error_copy (error);
-      g_error_free (error);
-      return NULL;
-    }
-
-  portal = g_new0 (PortalData, 1);
-  portal->proxy = proxy;
-  portal->op = g_object_ref (op);
-  portal->parent = parent;
-  portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  portal->print_cb = print_cb;
-
-  if (print_cb) /* async case */
-    {
-      portal->loop = NULL;
-      portal->destroy = portal_data_free;
-    }
-  else
-    {
-      portal->loop = g_main_loop_new (NULL, FALSE);
-      portal->destroy = NULL;
-    }
-
-  return portal;
-}
-
-static void
-window_handle_exported (GtkWindow  *window,
-                        const char *handle_str,
-                        gpointer    user_data)
-{
-  PortalData *portal = user_data;
-
-  portal->handle = g_strdup (handle_str);
-
-  g_dbus_proxy_call (portal->proxy,
-                     "PreparePrint",
-                     g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
-                                    handle_str,
-                                    _("Print"), /* title */
-                                    portal->settings,
-                                    portal->setup,
-                                    portal->options),
-                     G_DBUS_CALL_FLAGS_NONE,
-                     -1,
-                     NULL,
-                     prepare_print_called,
-                     portal);
-}
-
-static void
-call_prepare_print (GtkPrintOperation *op,
-                    PortalData        *portal)
-{
-  GtkPrintOperationPrivate *priv = op->priv;
-  GVariantBuilder opt_builder;
-  char *token;
-
-  portal->prepare_print_handle =
-      gtk_get_portal_request_path (g_dbus_proxy_get_connection (portal->proxy), &token);
-
-  portal->response_signal_id =
-    g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
-                                        PORTAL_BUS_NAME,
-                                        PORTAL_REQUEST_INTERFACE,
-                                        "Response",
-                                        portal->prepare_print_handle,
-                                        NULL,
-                                        G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
-                                        prepare_print_response,
-                                        portal, NULL);
-
-  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
-  g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
-  g_free (token);
-  portal->options = g_variant_builder_end (&opt_builder);
-
-  if (priv->print_settings)
-    portal->settings = gtk_print_settings_to_gvariant (priv->print_settings);
-  else
-    {
-      GVariantBuilder builder;
-      g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
-      portal->settings = g_variant_builder_end (&builder);
-    }
-
-  if (priv->default_page_setup)
-    portal->setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
-  else
-    {
-      GtkPageSetup *page_setup = gtk_page_setup_new ();
-      portal->setup = gtk_page_setup_to_gvariant (page_setup);
-      g_object_unref (page_setup);
-    }
-
-  g_variant_ref_sink (portal->options);
-  g_variant_ref_sink (portal->settings);
-  g_variant_ref_sink (portal->setup);
-
-  if (portal->parent != NULL &&
-      gtk_widget_is_visible (GTK_WIDGET (portal->parent)) &&
-      gtk_window_export_handle (portal->parent, window_handle_exported, portal))
-    return;
-
-  g_dbus_proxy_call (portal->proxy,
-                     "PreparePrint",
-                     g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
-                                    "",
-                                    _("Print"), /* title */
-                                    portal->settings,
-                                    portal->setup,
-                                    portal->options),
-                     G_DBUS_CALL_FLAGS_NONE,
-                     -1,
-                     NULL,
-                     prepare_print_called,
-                     portal);
-}
-
-GtkPrintOperationResult
-gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
-                                       gboolean           show_dialog,
-                                       GtkWindow         *parent,
-                                       gboolean          *do_print)
-{
-  PortalData *portal;
-  GtkPrintOperationResult result;
-
-  portal = create_portal_data (op, parent, NULL);
-  if (portal == NULL)
-    return GTK_PRINT_OPERATION_RESULT_ERROR;
-
-  call_prepare_print (op, portal);
-
-  g_main_loop_run (portal->loop);
-
-  *do_print = portal->do_print;
-  result = portal->result;
-
-  portal_data_free (portal);
-
-  return result;
-}
-
-void
-gtk_print_operation_portal_run_dialog_async (GtkPrintOperation          *op,
-                                             gboolean                    show_dialog,
-                                             GtkWindow                  *parent,
-                                             GtkPrintOperationPrintFunc  print_cb)
-{
-  PortalData *portal;
-
-  portal = create_portal_data (op, parent, print_cb);
-  if (portal == NULL)
-    return;
-
-  call_prepare_print (op, portal);
-}
-
-void
-gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
-                                           cairo_surface_t   *surface,
-                                           GtkWindow         *parent,
-                                           const char        *filename)
-{
-  GFile *file;
-  GtkFileLauncher *launcher;
-
-  file = g_file_new_for_path (filename);
-  launcher = gtk_file_launcher_new (file);
-  gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
-  g_object_unref (launcher);
-  g_object_unref (file);
-}
diff --git a/gtk/gtkprintoperation-portal.h b/gtk/gtkprintoperation-portal.h
deleted file mode 100644 (file)
index 6aa1219..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "print/gtkprintoperation.h"
-
-G_BEGIN_DECLS
-
-GtkPrintOperationResult gtk_print_operation_portal_run_dialog             (GtkPrintOperation           *op,
-                                                                           gboolean                     show_dialog,
-                                                                           GtkWindow                   *parent,
-                                                                           gboolean                    *do_print);
-void                    gtk_print_operation_portal_run_dialog_async       (GtkPrintOperation           *op,
-                                                                           gboolean                     show_dialog,
-                                                                           GtkWindow                   *parent,
-                                                                           GtkPrintOperationPrintFunc   print_cb);
-void                    gtk_print_operation_portal_launch_preview         (GtkPrintOperation           *op,
-                                                                           cairo_surface_t             *surface,
-                                                                           GtkWindow                   *parent,
-                                                                           const char                  *filename);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h
deleted file mode 100644 (file)
index f5daa45..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "print/gtkprintoperation.h"
-
-G_BEGIN_DECLS
-
-/* Page drawing states */
-typedef enum
-{
-  GTK_PAGE_DRAWING_STATE_READY,
-  GTK_PAGE_DRAWING_STATE_DRAWING,
-  GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING
-} GtkPageDrawingState;
-
-struct _GtkPrintOperationPrivate
-{
-  GtkPrintOperationAction action;
-  GtkPrintStatus status;
-  GError *error;
-  char *status_string;
-  GtkPageSetup *default_page_setup;
-  GtkPrintSettings *print_settings;
-  char *job_name;
-  int nr_of_pages;
-  int nr_of_pages_to_print;
-  int page_position;
-  int current_page;
-  GtkUnit unit;
-  char *export_filename;
-  guint use_full_page      : 1;
-  guint track_print_status : 1;
-  guint show_progress      : 1;
-  guint cancelled          : 1;
-  guint allow_async        : 1;
-  guint is_sync            : 1;
-  guint support_selection  : 1;
-  guint has_selection      : 1;
-  guint embed_page_setup   : 1;
-
-  GtkPageDrawingState      page_drawing_state;
-
-  guint print_pages_idle_id;
-  guint show_progress_timeout_id;
-
-  GtkPrintContext *print_context;
-  
-  GtkPrintPages print_pages;
-  GtkPageRange *page_ranges;
-  int num_page_ranges;
-  
-  int manual_num_copies;
-  guint manual_collation   : 1;
-  guint manual_reverse     : 1;
-  guint manual_orientation : 1;
-  double manual_scale;
-  GtkPageSet manual_page_set;
-  guint manual_number_up;
-  GtkNumberUpLayout manual_number_up_layout;
-
-  GtkWidget *custom_widget;
-  char *custom_tab_label;
-  
-  gpointer platform_data;
-  GDestroyNotify free_platform_data;
-
-  GMainLoop *rloop; /* recursive mainloop */
-
-  void (*start_page) (GtkPrintOperation *operation,
-                     GtkPrintContext   *print_context,
-                     GtkPageSetup      *page_setup);
-  void (*end_page)   (GtkPrintOperation *operation,
-                     GtkPrintContext   *print_context);
-  void (*end_run)    (GtkPrintOperation *operation,
-                     gboolean           wait,
-                     gboolean           cancelled);
-};
-
-
-typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation      *op,
-                                            GtkWindow              *parent,
-                                            gboolean                do_print,
-                                            GtkPrintOperationResult result);
-
-GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog             (GtkPrintOperation           *operation,
-                                                                                     gboolean                     show_dialog,
-                                                                                     GtkWindow                   *parent,
-                                                                                     gboolean                    *do_print);
-void                    _gtk_print_operation_platform_backend_run_dialog_async       (GtkPrintOperation           *op,
-                                                                                     gboolean                     show_dialog,
-                                                                                     GtkWindow                   *parent,
-                                                                                     GtkPrintOperationPrintFunc   print_cb);
-void                    _gtk_print_operation_platform_backend_launch_preview         (GtkPrintOperation           *op,
-                                                                                     cairo_surface_t             *surface,
-                                                                                     GtkWindow                   *parent,
-                                                                                     const char                  *filename);
-cairo_surface_t *       _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation           *op,
-                                                                                     GtkPageSetup                *page_setup,
-                                                                                     double                      *dpi_x,
-                                                                                     double                      *dpi_y,
-                                                                                     char                        **target);
-void                    _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation           *op,
-                                                                                     GtkPageSetup                *page_setup,
-                                                                                     cairo_surface_t             *surface);
-void                    _gtk_print_operation_platform_backend_preview_start_page     (GtkPrintOperation *op,
-                                                                                     cairo_surface_t *surface,
-                                                                                     cairo_t *cr);
-void                    _gtk_print_operation_platform_backend_preview_end_page       (GtkPrintOperation *op,
-                                                                                     cairo_surface_t *surface,
-                                                                                     cairo_t *cr);
-
-void _gtk_print_operation_set_status (GtkPrintOperation *op,
-                                     GtkPrintStatus     status,
-                                     const char        *string);
-
-/* GtkPrintContext private functions: */
-
-GtkPrintContext *_gtk_print_context_new                             (GtkPrintOperation *op);
-void             _gtk_print_context_set_page_setup                  (GtkPrintContext   *context,
-                                                                    GtkPageSetup      *page_setup);
-void             _gtk_print_context_translate_into_margin           (GtkPrintContext   *context);
-void             _gtk_print_context_rotate_according_to_orientation (GtkPrintContext   *context);
-void             _gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context);
-void             _gtk_print_context_set_hard_margins                (GtkPrintContext   *context,
-                                                                    double             top,
-                                                                    double             bottom,
-                                                                    double             left,
-                                                                    double             right);
-
-G_END_DECLS
-
diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c
deleted file mode 100644 (file)
index 1108927..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include <glib/gstdio.h>
-#include "gtkprintoperation-private.h"
-#include "gtkprintoperation-portal.h"
-
-#include <cairo-pdf.h>
-#include <cairo-ps.h>
-#include "gtkprivate.h"
-#include "gtkprintunixdialog.h"
-#include "gtkpagesetupunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprinter.h"
-#include "gtkprintjob.h"
-#include "gtklabel.h"
-#include "gtkfilelauncher.h"
-#include <glib/gi18n-lib.h>
-
-
-typedef struct
-{
-  GtkWindow *parent;        /* just in case we need to throw error dialogs */
-  GMainLoop *loop;
-  gboolean data_sent;
-
-  /* Real printing (not preview) */
-  GtkPrintJob *job;         /* the job we are sending to the printer */
-  cairo_surface_t *surface;
-  gulong job_status_changed_tag;
-
-
-} GtkPrintOperationUnix;
-
-typedef struct _PrinterFinder PrinterFinder;
-
-static void printer_finder_free (PrinterFinder *finder);
-static void find_printer        (const char    *printer,
-                                GFunc          func,
-                                gpointer       data);
-
-static void
-unix_start_page (GtkPrintOperation *op,
-                GtkPrintContext   *print_context,
-                GtkPageSetup      *page_setup)
-{
-  GtkPrintOperationUnix *op_unix;
-  GtkPaperSize *paper_size;
-  cairo_surface_type_t type;
-  double w, h;
-
-  op_unix = op->priv->platform_data;
-
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-
-  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
-  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
-  type = cairo_surface_get_type (op_unix->surface);
-
-  if ((op->priv->manual_number_up < 2) ||
-      (op->priv->page_position % op->priv->manual_number_up == 0))
-    {
-      if (type == CAIRO_SURFACE_TYPE_PS)
-        {
-          cairo_ps_surface_set_size (op_unix->surface, w, h);
-          cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
-          switch (gtk_page_setup_get_orientation (page_setup))
-            {
-              case GTK_PAGE_ORIENTATION_PORTRAIT:
-              case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
-                break;
-
-              case GTK_PAGE_ORIENTATION_LANDSCAPE:
-              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
-                break;
-              default:
-                break;
-            }
-         }
-      else if (type == CAIRO_SURFACE_TYPE_PDF)
-        {
-          if (!op->priv->manual_orientation)
-            {
-              w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
-              h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
-            }
-          cairo_pdf_surface_set_size (op_unix->surface, w, h);
-        }
-    }
-}
-
-static void
-unix_end_page (GtkPrintOperation *op,
-              GtkPrintContext   *print_context)
-{
-  cairo_t *cr;
-
-  cr = gtk_print_context_get_cairo_context (print_context);
-
-  if ((op->priv->manual_number_up < 2) ||
-      ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
-      (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
-    cairo_show_page (cr);
-}
-
-static void
-op_unix_free (GtkPrintOperationUnix *op_unix)
-{
-  if (op_unix->job)
-    {
-      if (op_unix->job_status_changed_tag > 0)
-        g_signal_handler_disconnect (op_unix->job,
-                                    op_unix->job_status_changed_tag);
-      g_object_unref (op_unix->job);
-    }
-
-  g_free (op_unix);
-}
-
-static char *
-shell_command_substitute_file (const char *cmd,
-                              const char *pdf_filename,
-                              const char *settings_filename,
-                               gboolean    *pdf_filename_replaced,
-                               gboolean    *settings_filename_replaced)
-{
-  const char *inptr, *start;
-  GString *final;
-
-  g_return_val_if_fail (cmd != NULL, NULL);
-  g_return_val_if_fail (pdf_filename != NULL, NULL);
-  g_return_val_if_fail (settings_filename != NULL, NULL);
-
-  final = g_string_new (NULL);
-
-  *pdf_filename_replaced = FALSE;
-  *settings_filename_replaced = FALSE;
-
-  start = inptr = cmd;
-  while ((inptr = strchr (inptr, '%')) != NULL)
-    {
-      g_string_append_len (final, start, inptr - start);
-      inptr++;
-      switch (*inptr)
-        {
-          case 'f':
-            g_string_append (final, pdf_filename);
-            *pdf_filename_replaced = TRUE;
-            break;
-
-          case 's':
-            g_string_append (final, settings_filename);
-            *settings_filename_replaced = TRUE;
-            break;
-
-          case '%':
-            g_string_append_c (final, '%');
-            break;
-
-          default:
-            g_string_append_c (final, '%');
-            if (*inptr)
-              g_string_append_c (final, *inptr);
-            break;
-        }
-      if (*inptr)
-        inptr++;
-      start = inptr;
-    }
-  g_string_append (final, start);
-
-  return g_string_free (final, FALSE);
-}
-
-static void
-gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
-                                         cairo_surface_t   *surface,
-                                         GtkWindow         *parent,
-                                         const char        *filename)
-{
-  GAppInfo *appinfo;
-  GdkAppLaunchContext *context;
-  char *cmd;
-  char *preview_cmd;
-  GtkSettings *settings;
-  GtkPrintSettings *print_settings = NULL;
-  GtkPageSetup *page_setup;
-  GKeyFile *key_file = NULL;
-  char *data = NULL;
-  gsize data_len;
-  char *settings_filename = NULL;
-  char *quoted_filename;
-  char *quoted_settings_filename;
-  gboolean filename_used = FALSE;
-  gboolean settings_used = FALSE;
-  GdkDisplay *display;
-  GError *error = NULL;
-  int fd;
-  gboolean retval;
-
-  cairo_surface_destroy (surface);
-
-  if (parent)
-    display = gtk_widget_get_display (GTK_WIDGET (parent));
-  else
-    display = gdk_display_get_default ();
-
-  fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
-  if (fd < 0)
-    goto out;
-
-  key_file = g_key_file_new ();
-
-  print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op));
-
-  if (print_settings != NULL)
-    {
-      gtk_print_settings_set_reverse (print_settings, FALSE);
-      gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL);
-      gtk_print_settings_set_scale (print_settings, 1.0);
-      gtk_print_settings_set_number_up (print_settings, 1);
-      gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
-
-      /*  These removals are necessary because cups-* settings have higher priority
-       *  than normal settings.
-       */
-      gtk_print_settings_unset (print_settings, "cups-reverse");
-      gtk_print_settings_unset (print_settings, "cups-page-set");
-      gtk_print_settings_unset (print_settings, "cups-scale");
-      gtk_print_settings_unset (print_settings, "cups-number-up");
-      gtk_print_settings_unset (print_settings, "cups-number-up-layout");
-
-      gtk_print_settings_to_key_file (print_settings, key_file, NULL);
-      g_object_unref (print_settings);
-    }
-
-  page_setup = gtk_print_context_get_page_setup (op->priv->print_context);
-  gtk_page_setup_to_key_file (page_setup, key_file, NULL);
-
-  g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);
-
-  data = g_key_file_to_data (key_file, &data_len, &error);
-  if (!data)
-    goto out;
-
-  retval = g_file_set_contents (settings_filename, data, data_len, &error);
-  if (!retval)
-    goto out;
-
-  settings = gtk_settings_get_for_display (display);
-  g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);
-
-  quoted_filename = g_shell_quote (filename);
-  quoted_settings_filename = g_shell_quote (settings_filename);
-  cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
-
-  appinfo = g_app_info_create_from_commandline (cmd,
-                                                "Print Preview",
-                                                G_APP_INFO_CREATE_NONE,
-                                                &error);
-
-  g_free (preview_cmd);
-  g_free (quoted_filename);
-  g_free (quoted_settings_filename);
-  g_free (cmd);
-
-  if (error != NULL)
-    goto out;
-
-  context = gdk_display_get_app_launch_context (display);
-  g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
-
-  g_object_unref (context);
-  g_object_unref (appinfo);
-
-  if (error != NULL)
-    {
-      GFile *file;
-      GtkFileLauncher *launcher;
-
-      g_warning ("Error launching preview: %s", error->message);
-      g_clear_error (&error);
-
-      file = g_file_new_for_path (filename);
-      launcher = gtk_file_launcher_new (file);
-      gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
-      g_object_unref (launcher);
-      g_object_unref (file);
-    }
-
- out:
-  if (error != NULL)
-    {
-      if (op->priv->error == NULL)
-        op->priv->error = error;
-      else
-        g_error_free (error);
-
-      filename_used = FALSE;
-      settings_used = FALSE;
-   }
-
-  if (!filename_used)
-    g_unlink (filename);
-
-  if (!settings_used)
-    g_unlink (settings_filename);
-
-  if (fd > 0)
-    close (fd);
-
-  if (key_file)
-    g_key_file_free (key_file);
-  g_free (data);
-  g_free (settings_filename);
-}
-
-static void
-unix_finish_send  (GtkPrintJob  *job,
-                   gpointer      user_data,
-                   const GError *error)
-{
-  GtkPrintOperation *op = (GtkPrintOperation *) user_data;
-  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
-
-  if (error != NULL && op->priv->error == NULL)
-    op->priv->error = g_error_copy (error);
-
-  op_unix->data_sent = TRUE;
-
-  if (op_unix->loop)
-    g_main_loop_quit (op_unix->loop);
-
-  g_object_unref (op);
-}
-
-static void
-unix_end_run (GtkPrintOperation *op,
-             gboolean           wait,
-             gboolean           cancelled)
-{
-  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
-
-  cairo_surface_finish (op_unix->surface);
-
-  if (cancelled)
-    return;
-
-  if (wait)
-    op_unix->loop = g_main_loop_new (NULL, FALSE);
-
-  /* TODO: Check for error */
-  if (op_unix->job != NULL)
-    {
-      g_object_ref (op);
-      gtk_print_job_send (op_unix->job,
-                          unix_finish_send,
-                          op, NULL);
-    }
-
-  if (wait)
-    {
-      g_object_ref (op);
-      if (!op_unix->data_sent)
-       g_main_loop_run (op_unix->loop);
-      g_main_loop_unref (op_unix->loop);
-      op_unix->loop = NULL;
-      g_object_unref (op);
-    }
-}
-
-static void
-job_status_changed_cb (GtkPrintJob       *job,
-                      GtkPrintOperation *op)
-{
-  _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
-}
-
-
-static void
-print_setup_changed_cb (GtkPrintUnixDialog *print_dialog,
-                        GParamSpec         *pspec,
-                        gpointer            user_data)
-{
-  GtkPageSetup             *page_setup;
-  GtkPrintSettings         *print_settings;
-  GtkPrintOperation        *op = user_data;
-  GtkPrintOperationPrivate *priv = op->priv;
-
-  page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog);
-  print_settings = gtk_print_unix_dialog_get_settings (print_dialog);
-
-  g_signal_emit_by_name (op,
-                         "update-custom-widget",
-                         priv->custom_widget,
-                         page_setup,
-                         print_settings);
-}
-
-static GtkWidget *
-get_print_dialog (GtkPrintOperation *op,
-                  GtkWindow         *parent)
-{
-  GtkPrintOperationPrivate *priv = op->priv;
-  GtkWidget *pd, *label;
-  const char *custom_tab_label;
-
-  pd = gtk_print_unix_dialog_new (NULL, parent);
-
-  gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd),
-                                                GTK_PRINT_CAPABILITY_PAGE_SET |
-                                                GTK_PRINT_CAPABILITY_COPIES |
-                                                GTK_PRINT_CAPABILITY_COLLATE |
-                                                GTK_PRINT_CAPABILITY_REVERSE |
-                                                GTK_PRINT_CAPABILITY_SCALE |
-                                                GTK_PRINT_CAPABILITY_PREVIEW |
-                                                GTK_PRINT_CAPABILITY_NUMBER_UP |
-                                                GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
-
-  if (priv->print_settings)
-    gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
-                                       priv->print_settings);
-
-  if (priv->default_page_setup)
-    gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
-                                          priv->default_page_setup);
-
-  gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
-                                              priv->embed_page_setup);
-
-  gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd),
-                                          priv->current_page);
-
-  gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd),
-                                               priv->support_selection);
-
-  gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd),
-                                           priv->has_selection);
-
-  g_signal_emit_by_name (op, "create-custom-widget",
-                        &priv->custom_widget);
-
-  if (priv->custom_widget)
-    {
-      custom_tab_label = priv->custom_tab_label;
-
-      if (custom_tab_label == NULL)
-       {
-         custom_tab_label = g_get_application_name ();
-         if (custom_tab_label == NULL)
-           custom_tab_label = _("Application");
-       }
-
-      label = gtk_label_new (custom_tab_label);
-
-      gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd),
-                                           priv->custom_widget, label);
-
-      g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op);
-      g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op);
-    }
-
-  return pd;
-}
-
-typedef struct
-{
-  GtkPrintOperation           *op;
-  gboolean                     do_print;
-  gboolean                     do_preview;
-  GtkPrintOperationResult      result;
-  GtkPrintOperationPrintFunc   print_cb;
-  GDestroyNotify               destroy;
-  GtkWindow                   *parent;
-  GMainLoop                   *loop;
-} PrintResponseData;
-
-static void
-print_response_data_free (gpointer data)
-{
-  PrintResponseData *rdata = data;
-
-  g_object_unref (rdata->op);
-  g_free (rdata);
-}
-
-static void
-finish_print (PrintResponseData *rdata,
-             GtkPrinter        *printer,
-             GtkPageSetup      *page_setup,
-             GtkPrintSettings  *settings,
-             gboolean           page_setup_set)
-{
-  GtkPrintOperation *op = rdata->op;
-  GtkPrintOperationPrivate *priv = op->priv;
-  GtkPrintJob *job;
-  double top, bottom, left, right;
-
-  if (rdata->do_print)
-    {
-      gtk_print_operation_set_print_settings (op, settings);
-      priv->print_context = _gtk_print_context_new (op);
-
-      if (gtk_print_settings_get_number_up (settings) < 2)
-        {
-         if (printer && (gtk_printer_get_hard_margins_for_paper_size (printer, gtk_page_setup_get_paper_size (page_setup), &top, &bottom, &left, &right) ||
-                         gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)))
-           _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
-       }
-      else
-        {
-         /* Pages do not have any unprintable area when printing n-up as each page on the
-          * sheet has been scaled down and translated to a position within the printable
-          * area of the sheet.
-          */
-         _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
-       }
-
-      if (page_setup != NULL &&
-          (gtk_print_operation_get_default_page_setup (op) == NULL ||
-           page_setup_set))
-        gtk_print_operation_set_default_page_setup (op, page_setup);
-
-      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-
-      if (!rdata->do_preview)
-        {
-         GtkPrintOperationUnix *op_unix;
-         cairo_t *cr;
-
-         op_unix = g_new0 (GtkPrintOperationUnix, 1);
-         priv->platform_data = op_unix;
-         priv->free_platform_data = (GDestroyNotify) op_unix_free;
-         op_unix->parent = rdata->parent;
-
-         priv->start_page = unix_start_page;
-         priv->end_page = unix_end_page;
-         priv->end_run = unix_end_run;
-
-         job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
-          op_unix->job = job;
-          gtk_print_job_set_track_print_status (job, priv->track_print_status);
-
-         op_unix->surface = gtk_print_job_get_surface (job, &priv->error);
-         if (op_unix->surface == NULL)
-            {
-             rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
-             rdata->do_print = FALSE;
-             goto out;
-            }
-
-         cr = cairo_create (op_unix->surface);
-         gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
-         cairo_destroy (cr);
-
-          _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
-
-          op_unix->job_status_changed_tag =
-           g_signal_connect (job, "status-changed",
-                             G_CALLBACK (job_status_changed_cb), op);
-
-          priv->print_pages = gtk_print_job_get_pages (job);
-          priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
-          priv->manual_num_copies = gtk_print_job_get_num_copies (job);
-          priv->manual_collation = gtk_print_job_get_collate (job);
-          priv->manual_reverse = gtk_print_job_get_reverse (job);
-          priv->manual_page_set = gtk_print_job_get_page_set (job);
-          priv->manual_scale = gtk_print_job_get_scale (job);
-          priv->manual_orientation = gtk_print_job_get_rotate (job);
-          priv->manual_number_up = gtk_print_job_get_n_up (job);
-          priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
-        }
-    }
- out:
-  if (rdata->print_cb)
-    rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result);
-
-  if (rdata->destroy)
-    rdata->destroy (rdata);
-}
-
-static void
-handle_print_response (GtkWidget *dialog,
-                      int        response,
-                      gpointer   data)
-{
-  GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
-  PrintResponseData *rdata = data;
-  GtkPrintSettings *settings = NULL;
-  GtkPageSetup *page_setup = NULL;
-  GtkPrinter *printer = NULL;
-  gboolean page_setup_set = FALSE;
-
-  if (response == GTK_RESPONSE_OK)
-    {
-      printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
-
-      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-      rdata->do_preview = FALSE;
-      if (printer != NULL)
-       rdata->do_print = TRUE;
-    }
-  else if (response == GTK_RESPONSE_APPLY)
-    {
-      /* print preview */
-      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-      rdata->do_preview = TRUE;
-      rdata->do_print = TRUE;
-
-      rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
-    }
-
-  if (rdata->do_print)
-    {
-      settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
-      page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
-      page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd));
-
-      /* Set new print settings now so that custom-widget options
-       * can be added to the settings in the callback
-       */
-      gtk_print_operation_set_print_settings (rdata->op, settings);
-      g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
-    }
-
-  if (rdata->loop)
-    g_main_loop_quit (rdata->loop);
-
-  finish_print (rdata, printer, page_setup, settings, page_setup_set);
-
-  if (settings)
-    g_object_unref (settings);
-
-  gtk_window_destroy (GTK_WINDOW (pd));
-}
-
-
-static void
-found_printer (GtkPrinter        *printer,
-              PrintResponseData *rdata)
-{
-  GtkPrintOperation *op = rdata->op;
-  GtkPrintOperationPrivate *priv = op->priv;
-  GtkPrintSettings *settings = NULL;
-  GtkPageSetup *page_setup = NULL;
-
-  if (rdata->loop)
-    g_main_loop_quit (rdata->loop);
-
-  if (printer != NULL)
-    {
-      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
-      rdata->do_print = TRUE;
-
-      if (priv->print_settings)
-       settings = gtk_print_settings_copy (priv->print_settings);
-      else
-       settings = gtk_print_settings_new ();
-
-      gtk_print_settings_set_printer (settings,
-                                     gtk_printer_get_name (printer));
-
-      if (priv->default_page_setup)
-       page_setup = gtk_page_setup_copy (priv->default_page_setup);
-      else
-       page_setup = gtk_page_setup_new ();
-  }
-
-  finish_print (rdata, printer, page_setup, settings, FALSE);
-
-  if (settings)
-    g_object_unref (settings);
-
-  if (page_setup)
-    g_object_unref (page_setup);
-}
-
-static void
-gtk_print_operation_unix_run_dialog_async (GtkPrintOperation          *op,
-                                           gboolean                    show_dialog,
-                                           GtkWindow                  *parent,
-                                           GtkPrintOperationPrintFunc  print_cb)
-{
-  GtkWidget *pd;
-  PrintResponseData *rdata;
-  const char *printer_name;
-
-  rdata = g_new (PrintResponseData, 1);
-  rdata->op = g_object_ref (op);
-  rdata->do_print = FALSE;
-  rdata->do_preview = FALSE;
-  rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  rdata->print_cb = print_cb;
-  rdata->parent = parent;
-  rdata->loop = NULL;
-  rdata->destroy = print_response_data_free;
-
-  if (show_dialog)
-    {
-      pd = get_print_dialog (op, parent);
-      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
-      g_signal_connect (pd, "response",
-                       G_CALLBACK (handle_print_response), rdata);
-
-      gtk_window_present (GTK_WINDOW (pd));
-    }
-  else
-    {
-      printer_name = NULL;
-      if (op->priv->print_settings)
-       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
-
-      find_printer (printer_name, (GFunc) found_printer, rdata);
-    }
-}
-
-static cairo_status_t
-write_preview (void                *closure,
-               const unsigned char *data,
-               unsigned int         length)
-{
-  int fd = GPOINTER_TO_INT (closure);
-  gssize written;
-
-  while (length > 0)
-    {
-      written = write (fd, data, length);
-
-      if (written == -1)
-       {
-         if (errno == EAGAIN || errno == EINTR)
-           continue;
-
-         return CAIRO_STATUS_WRITE_ERROR;
-       }
-
-      data += written;
-      length -= written;
-    }
-
-  return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-close_preview (void *data)
-{
-  int fd = GPOINTER_TO_INT (data);
-
-  close (fd);
-}
-
-static cairo_surface_t *
-gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
-                                                 GtkPageSetup      *page_setup,
-                                                 double            *dpi_x,
-                                                 double            *dpi_y,
-                                                 char             **target)
-{
-  char *filename;
-  int fd;
-  GtkPaperSize *paper_size;
-  double w, h;
-  cairo_surface_t *surface;
-  static cairo_user_data_key_t key;
-
-  filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL);
-  fd = g_mkstemp (filename);
-
-  if (fd < 0)
-    {
-      g_free (filename);
-      return NULL;
-    }
-
-  *target = filename;
-
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
-  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
-
-  *dpi_x = *dpi_y = 72;
-  surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h);
-
-  cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview);
-
-  return surface;
-}
-
-static void
-gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
-                                             cairo_surface_t   *surface,
-                                             cairo_t           *cr)
-{
-}
-
-static void
-gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
-                                           cairo_surface_t   *surface,
-                                           cairo_t           *cr)
-{
-  cairo_show_page (cr);
-}
-
-static void
-gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
-                                                 GtkPageSetup      *page_setup,
-                                                 cairo_surface_t   *surface)
-{
-  double w, h;
-
-  w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
-  h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
-  cairo_pdf_surface_set_size (surface, w, h);
-}
-
-static GtkPrintOperationResult
-gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
-                                     gboolean           show_dialog,
-                                     GtkWindow         *parent,
-                                     gboolean          *do_print)
- {
-  GtkWidget *pd;
-  PrintResponseData rdata;
-  const char *printer_name;
-
-  rdata.op = op;
-  rdata.do_print = FALSE;
-  rdata.do_preview = FALSE;
-  rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  rdata.print_cb = NULL;
-  rdata.destroy = NULL;
-  rdata.parent = parent;
-  rdata.loop = NULL;
-
-  if (show_dialog)
-    {
-      pd = get_print_dialog (op, parent);
-      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
-
-      g_signal_connect (pd, "response",
-                       G_CALLBACK (handle_print_response), &rdata);
-
-      gtk_window_present (GTK_WINDOW (pd));
-
-      rdata.loop = g_main_loop_new (NULL, FALSE);
-      g_main_loop_run (rdata.loop);
-      g_main_loop_unref (rdata.loop);
-      rdata.loop = NULL;
-    }
-  else
-    {
-      printer_name = NULL;
-      if (op->priv->print_settings)
-       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
-
-      rdata.loop = g_main_loop_new (NULL, FALSE);
-      find_printer (printer_name,
-                   (GFunc) found_printer, &rdata);
-
-      g_main_loop_run (rdata.loop);
-      g_main_loop_unref (rdata.loop);
-      rdata.loop = NULL;
-    }
-
-  *do_print = rdata.do_print;
-
-  return rdata.result;
-}
-
-
-typedef struct
-{
-  GtkPageSetup         *page_setup;
-  GtkPageSetupDoneFunc  done_cb;
-  gpointer              data;
-  GDestroyNotify        destroy;
-  GMainLoop            *loop;
-} PageSetupResponseData;
-
-static void
-page_setup_data_free (gpointer data)
-{
-  PageSetupResponseData *rdata = data;
-
-  if (rdata->page_setup)
-    g_object_unref (rdata->page_setup);
-
-  g_free (rdata);
-}
-
-static void
-handle_page_setup_response (GtkWidget *dialog,
-                           int        response,
-                           gpointer   data)
-{
-  GtkPageSetupUnixDialog *psd;
-  PageSetupResponseData *rdata = data;
-
-  if (rdata->loop)
-    g_main_loop_quit (rdata->loop);
-
-  psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
-  if (response == GTK_RESPONSE_OK)
-    rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
-
-  gtk_window_destroy (GTK_WINDOW (dialog));
-
-  if (rdata->done_cb)
-    rdata->done_cb (rdata->page_setup, rdata->data);
-
-  if (rdata->destroy)
-    rdata->destroy (rdata);
-}
-
-static GtkWidget *
-get_page_setup_dialog (GtkWindow        *parent,
-                      GtkPageSetup     *page_setup,
-                      GtkPrintSettings *settings)
-{
-  GtkWidget *dialog;
-
-  dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
-  if (page_setup)
-    gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
-                                              page_setup);
-  gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
-                                                settings);
-
-  return dialog;
-}
-
-/**
- * gtk_print_run_page_setup_dialog:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- *
- * Runs a page setup dialog, letting the user modify the values from
- * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
- * is identical to the passed in @page_setup, otherwise it contains the
- * modifications done in the dialog.
- *
- * Note that this function may use a recursive mainloop to show the page
- * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
- * a problem.
- *
- * Returns: (transfer full): a new `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_print_run_page_setup_dialog (GtkWindow        *parent,
-                                GtkPageSetup     *page_setup,
-                                GtkPrintSettings *settings)
-{
-  GtkWidget *dialog;
-  PageSetupResponseData rdata;
-
-  rdata.page_setup = NULL;
-  rdata.done_cb = NULL;
-  rdata.data = NULL;
-  rdata.destroy = NULL;
-  rdata.loop = g_main_loop_new (NULL, FALSE);
-
-  dialog = get_page_setup_dialog (parent, page_setup, settings);
-
-  g_signal_connect (dialog, "response",
-                    G_CALLBACK (handle_page_setup_response),
-                    &rdata);
-
-  gtk_window_present (GTK_WINDOW (dialog));
-
-  g_main_loop_run (rdata.loop);
-  g_main_loop_unref (rdata.loop);
-  rdata.loop = NULL;
-
-  if (rdata.page_setup)
-    return rdata.page_setup;
-  else if (page_setup)
-    return gtk_page_setup_copy (page_setup);
-  else
-    return gtk_page_setup_new ();
-}
-
-/**
- * gtk_print_run_page_setup_dialog_async:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- * @done_cb: (scope async): a function to call when the user saves
- *    the modified page setup
- * @data: user data to pass to @done_cb
- *
- * Runs a page setup dialog, letting the user modify the values from @page_setup.
- *
- * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after
- * showing the page setup dialog on platforms that support this, and calls @done_cb
- * from a signal handler for the ::response signal of the dialog.
- */
-void
-gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
-                                      GtkPageSetup         *page_setup,
-                                      GtkPrintSettings     *settings,
-                                      GtkPageSetupDoneFunc  done_cb,
-                                      gpointer              data)
-{
-  GtkWidget *dialog;
-  PageSetupResponseData *rdata;
-
-  dialog = get_page_setup_dialog (parent, page_setup, settings);
-  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-
-  rdata = g_new (PageSetupResponseData, 1);
-  rdata->page_setup = NULL;
-  rdata->done_cb = done_cb;
-  rdata->data = data;
-  rdata->destroy = page_setup_data_free;
-  rdata->loop = NULL;
-
-  g_signal_connect (dialog, "response",
-                   G_CALLBACK (handle_page_setup_response), rdata);
-
-  gtk_window_present (GTK_WINDOW (dialog));
- }
-
-struct _PrinterFinder
-{
-  gboolean found_printer;
-  GFunc func;
-  gpointer data;
-  char *printer_name;
-  GList *backends;
-  guint timeout_tag;
-  GtkPrinter *printer;
-  GtkPrinter *default_printer;
-  GtkPrinter *first_printer;
-};
-
-static gboolean
-find_printer_idle (gpointer data)
-{
-  PrinterFinder *finder = data;
-  GtkPrinter *printer;
-
-  if (finder->printer != NULL)
-    printer = finder->printer;
-  else if (finder->default_printer != NULL)
-    printer = finder->default_printer;
-  else if (finder->first_printer != NULL)
-    printer = finder->first_printer;
-  else
-    printer = NULL;
-
-  finder->func (printer, finder->data);
-
-  printer_finder_free (finder);
-
-  return G_SOURCE_REMOVE;
-}
-
-static void
-printer_added_cb (GtkPrintBackend *backend,
-                  GtkPrinter      *printer,
-                 PrinterFinder   *finder)
-{
-  if (finder->found_printer)
-    return;
-
-  /* FIXME this skips "Print to PDF" - is this intentional ? */
-  if (gtk_printer_is_virtual (printer))
-    return;
-
-  if (finder->printer_name != NULL &&
-      strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
-    {
-      finder->printer = g_object_ref (printer);
-      finder->found_printer = TRUE;
-    }
-  else if (finder->default_printer == NULL &&
-          gtk_printer_is_default (printer))
-    {
-      finder->default_printer = g_object_ref (printer);
-      if (finder->printer_name == NULL)
-       finder->found_printer = TRUE;
-    }
-  else
-    {
-      if (finder->first_printer == NULL)
-        finder->first_printer = g_object_ref (printer);
-    }
-
-  if (finder->found_printer)
-    g_idle_add (find_printer_idle, finder);
-}
-
-static void
-printer_list_done_cb (GtkPrintBackend *backend,
-                     PrinterFinder   *finder)
-{
-  finder->backends = g_list_remove (finder->backends, backend);
-
-  g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
-  g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
-
-  gtk_print_backend_destroy (backend);
-  g_object_unref (backend);
-
-  if (finder->backends == NULL)
-    g_idle_add (find_printer_idle, finder);
-}
-
-static void
-find_printer_init (PrinterFinder   *finder,
-                  GtkPrintBackend *backend)
-{
-  GList *list;
-  GList *node;
-
-  list = gtk_print_backend_get_printer_list (backend);
-
-  node = list;
-  while (node != NULL)
-    {
-      printer_added_cb (backend, node->data, finder);
-      node = node->next;
-
-      if (finder->found_printer)
-       break;
-    }
-
-  g_list_free (list);
-
-  if (gtk_print_backend_printer_list_is_done (backend))
-    {
-      finder->backends = g_list_remove (finder->backends, backend);
-      gtk_print_backend_destroy (backend);
-      g_object_unref (backend);
-    }
-  else
-    {
-      g_signal_connect (backend, "printer-added",
-                       (GCallback) printer_added_cb,
-                       finder);
-      g_signal_connect (backend, "printer-list-done",
-                       (GCallback) printer_list_done_cb,
-                       finder);
-    }
-
-}
-
-static void
-printer_finder_free (PrinterFinder *finder)
-{
-  GList *l;
-
-  g_free (finder->printer_name);
-
-  if (finder->printer)
-    g_object_unref (finder->printer);
-
-  if (finder->default_printer)
-    g_object_unref (finder->default_printer);
-
-  if (finder->first_printer)
-    g_object_unref (finder->first_printer);
-
-  for (l = finder->backends; l != NULL; l = l->next)
-    {
-      GtkPrintBackend *backend = l->data;
-      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
-      g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
-      gtk_print_backend_destroy (backend);
-      g_object_unref (backend);
-    }
-
-  g_list_free (finder->backends);
-
-  g_free (finder);
-}
-
-static void
-find_printer (const char *printer,
-             GFunc        func,
-             gpointer     data)
-{
-  GList *node, *next;
-  PrinterFinder *finder;
-
-  finder = g_new0 (PrinterFinder, 1);
-
-  finder->printer_name = g_strdup (printer);
-  finder->func = func;
-  finder->data = data;
-
-  finder->backends = NULL;
-  if (g_module_supported ())
-    finder->backends = gtk_print_backend_load_modules ();
-
-  for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
-    {
-      next = node->next;
-      find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
-    }
-
-  if (finder->backends == NULL)
-    g_idle_add (find_printer_idle, finder);
-}
-
-
-GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
-                                                 gboolean           show_dialog,
-                                                 GtkWindow         *parent,
-                                                 gboolean          *do_print)
-{
-  if (gdk_should_use_portal ())
-    return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
-  else
-    return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
-}
-void
-_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
-                                                       gboolean                    show_dialog,
-                                                        GtkWindow                  *parent,
-                                                       GtkPrintOperationPrintFunc  print_cb)
-{
-  if (gdk_should_use_portal ())
-    gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
-  else
-    gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
-}
-
-void
-_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
-                                                      cairo_surface_t   *surface,
-                                                      GtkWindow         *parent,
-                                                      const char        *filename)
-{
-  if (gdk_should_use_portal ())
-    gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
-  else
-    gtk_print_operation_unix_launch_preview (op, surface, parent, filename);
-}
-
-cairo_surface_t *
-_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             double            *dpi_x,
-                                                             double            *dpi_y,
-                                                             char             **target)
-{
-  return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
-}
-
-void
-_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             cairo_surface_t   *surface)
-{
-  gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
-                                                         cairo_surface_t   *surface,
-                                                         cairo_t           *cr)
-{
-  gtk_print_operation_unix_preview_start_page (op, surface, cr);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
-                                                       cairo_surface_t   *surface,
-                                                       cairo_t           *cr)
-{
-  gtk_print_operation_unix_preview_end_page (op, surface, cr);
-}
diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c
deleted file mode 100644 (file)
index 15d68ab..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _MSC_VER
-#ifndef _WIN32_WINNT
-/* Vista or newer */
-#define _WIN32_WINNT 0x0600
-#endif
-#ifndef WINVER
-#define WINVER _WIN32_WINNT
-#endif
-#endif
-
-#define COBJMACROS
-#include "config.h"
-#include <math.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <cairo-win32.h>
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-#include "gtkprintoperation-private.h"
-#include "gtkprint-win32.h"
-#include "gtkwindow.h"
-#include "gtkprivate.h"
-#include "gtkwidgetprivate.h"
-#include "gtknative.h"
-#include "win32/gdkprivate-win32.h"
-
-#define MAX_PAGE_RANGES 20
-#define STATUS_POLLING_TIME 2000
-
-#ifndef JOB_STATUS_RESTART
-#define JOB_STATUS_RESTART 0x800
-#endif
-
-#ifndef JOB_STATUS_COMPLETE
-#define JOB_STATUS_COMPLETE 0x1000
-#endif
-
-/* Forward declarations */
-GtkPrintOperationResult
-gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
-                                       gboolean          *do_print);
-GtkPrintOperationResult
-gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
-                                    GtkWindow         *parent,
-                                    gboolean          *do_print);
-UINT_PTR CALLBACK
-run_mainloop_hook (HWND hdlg,
-                  UINT uiMsg,
-                  WPARAM wParam,
-                  LPARAM lParam);
-void
-win32_start_page (GtkPrintOperation *op,
-                 GtkPrintContext *print_context,
-                 GtkPageSetup *page_setup);
-
-typedef struct {
-  HDC hdc;
-  HGLOBAL devmode;
-  HGLOBAL devnames;
-  HANDLE printerHandle;
-  int job_id;
-  guint timeout_id;
-
-  cairo_surface_t *surface;
-  GtkWidget *embed_widget;
-} GtkPrintOperationWin32;
-
-static void win32_poll_status (GtkPrintOperation *op);
-
-static const GUID myIID_IPrintDialogCallback  = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
-
-#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
-#undef INTERFACE
-#define INTERFACE IPrintDialogCallback
-DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
-{
-    STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
-    STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_ (ULONG, Release)(THIS) PURE;
-    STDMETHOD (InitDone)(THIS) PURE;
-    STDMETHOD (SelectionChange)(THIS) PURE;
-    STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
-}; 
-#endif
-
-static UINT got_gdk_events_message;
-
-UINT_PTR CALLBACK
-run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
-{
-  if (uiMsg == WM_INITDIALOG)
-    {
-      gdk_win32_set_modal_dialog_libgtk_only (hdlg);
-      while (g_main_context_pending (NULL))
-       g_main_context_iteration (NULL, TRUE);
-    }
-  else if (uiMsg == got_gdk_events_message)
-    {
-      while (g_main_context_pending (NULL))
-       g_main_context_iteration (NULL, TRUE);
-      return 1;
-    }
-  return 0;
-}
-
-static GtkPageOrientation
-orientation_from_win32 (short orientation)
-{
-  if (orientation == DMORIENT_LANDSCAPE)
-    return GTK_PAGE_ORIENTATION_LANDSCAPE;
-  return GTK_PAGE_ORIENTATION_PORTRAIT;
-}
-
-static short
-orientation_to_win32 (GtkPageOrientation orientation)
-{
-  if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
-      orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
-    return DMORIENT_LANDSCAPE;
-  return DMORIENT_PORTRAIT;
-}
-
-static GtkPaperSize *
-paper_size_from_win32 (short size)
-{
-  const char *name;
-  
-  switch (size)
-    {
-    case DMPAPER_LETTER_TRANSVERSE:
-    case DMPAPER_LETTER:
-    case DMPAPER_LETTERSMALL:
-      name = "na_letter";
-      break;
-    case DMPAPER_TABLOID:
-    case DMPAPER_LEDGER:
-      name = "na_ledger";
-      break;
-    case DMPAPER_LEGAL:
-      name = "na_legal";
-      break;
-    case DMPAPER_STATEMENT:
-      name = "na_invoice";
-      break;
-    case DMPAPER_EXECUTIVE:
-      name = "na_executive";
-      break;
-    case DMPAPER_A3:
-    case DMPAPER_A3_TRANSVERSE:
-      name = "iso_a3";
-      break;
-    case DMPAPER_A4:
-    case DMPAPER_A4SMALL:
-    case DMPAPER_A4_TRANSVERSE:
-      name = "iso_a4";
-      break;
-    case DMPAPER_A5:
-    case DMPAPER_A5_TRANSVERSE:
-      name = "iso_a5";
-      break;
-    case DMPAPER_B4:
-      name = "jis_b4";
-      break;
-    case DMPAPER_B5:
-    case DMPAPER_B5_TRANSVERSE:
-      name = "jis_b5";
-      break;
-    case DMPAPER_QUARTO:
-      name = "na_quarto";
-      break;
-    case DMPAPER_10X14:
-      name = "na_10x14";
-      break;
-    case DMPAPER_11X17:
-      name = "na_ledger";
-      break;
-    case DMPAPER_NOTE:
-      name = "na_letter";
-      break;
-    case DMPAPER_ENV_9:
-      name = "na_number-9";
-      break;
-    case DMPAPER_ENV_10:
-      name = "na_number-10";
-      break;
-    case DMPAPER_ENV_11:
-      name = "na_number-11";
-      break;
-    case DMPAPER_ENV_12:
-      name = "na_number-12";
-      break;
-    case DMPAPER_ENV_14:
-      name = "na_number-14";
-      break;
-    case DMPAPER_CSHEET:
-      name = "na_c";
-      break;
-    case DMPAPER_DSHEET:
-      name = "na_d";
-      break;
-    case DMPAPER_ESHEET:
-      name = "na_e";
-      break;
-    case DMPAPER_ENV_DL:
-      name = "iso_dl";
-      break;
-    case DMPAPER_ENV_C5:
-      name = "iso_c5";
-      break;
-    case DMPAPER_ENV_C3:
-      name = "iso_c3";
-      break;
-    case DMPAPER_ENV_C4:
-      name = "iso_c4";
-      break;
-    case DMPAPER_ENV_C6:
-      name = "iso_c6";
-      break;
-    case DMPAPER_ENV_C65:
-      name = "iso_c6c5";
-      break;
-    case DMPAPER_ENV_B4:
-      name = "iso_b4";
-      break;
-    case DMPAPER_ENV_B5:
-      name = "iso_b5";
-      break;
-    case DMPAPER_ENV_B6:
-      name = "iso_b6";
-      break;
-    case DMPAPER_ENV_ITALY:
-      name = "om_italian";
-      break;
-    case DMPAPER_ENV_MONARCH:
-      name = "na_monarch";
-      break;
-    case DMPAPER_ENV_PERSONAL:
-      name = "na_personal";
-      break;
-    case DMPAPER_FANFOLD_US:
-      name = "na_fanfold-us";
-      break;
-    case DMPAPER_FANFOLD_STD_GERMAN:
-      name = "na_fanfold-eur";
-      break;
-    case DMPAPER_FANFOLD_LGL_GERMAN:
-      name = "na_foolscap";
-      break;
-    case DMPAPER_ISO_B4:
-      name = "iso_b4";
-      break;
-    case DMPAPER_JAPANESE_POSTCARD:
-      name = "jpn_hagaki";
-      break;
-    case DMPAPER_9X11:
-      name = "na_9x11";
-      break;
-    case DMPAPER_10X11:
-      name = "na_10x11";
-      break;
-    case DMPAPER_ENV_INVITE:
-      name = "om_invite";
-       break;
-    case DMPAPER_LETTER_EXTRA:
-    case DMPAPER_LETTER_EXTRA_TRANSVERSE:
-      name = "na_letter-extra";
-      break;
-    case DMPAPER_LEGAL_EXTRA:
-      name = "na_legal-extra";
-      break;
-    case DMPAPER_TABLOID_EXTRA:
-      name = "na_arch";
-      break;
-    case DMPAPER_A4_EXTRA:
-      name = "iso_a4-extra";
-      break;
-    case DMPAPER_B_PLUS:
-      name = "na_b-plus";
-      break;
-    case DMPAPER_LETTER_PLUS:
-      name = "na_letter-plus";
-      break;
-    case DMPAPER_A3_EXTRA:
-    case DMPAPER_A3_EXTRA_TRANSVERSE:
-      name = "iso_a3-extra";
-      break;
-    case DMPAPER_A5_EXTRA:
-      name = "iso_a5-extra";
-      break;
-    case DMPAPER_B5_EXTRA:
-      name = "iso_b5-extra";
-      break;
-    case DMPAPER_A2:
-      name = "iso_a2";
-      break;
-      
-    default:
-      name = NULL;
-      break;
-    }
-
-  if (name)
-    return gtk_paper_size_new (name);
-  else 
-    return NULL;
-}
-
-static short
-paper_size_to_win32 (GtkPaperSize *paper_size)
-{
-  const char *format;
-
-  if (gtk_paper_size_is_custom (paper_size))
-    return 0;
-  
-  format = gtk_paper_size_get_name (paper_size);
-
-  if (strcmp (format, "na_letter") == 0)
-    return DMPAPER_LETTER;
-  if (strcmp (format, "na_ledger") == 0)
-    return DMPAPER_LEDGER;
-  if (strcmp (format, "na_legal") == 0)
-    return DMPAPER_LEGAL;
-  if (strcmp (format, "na_invoice") == 0)
-    return DMPAPER_STATEMENT;
-  if (strcmp (format, "na_executive") == 0)
-    return DMPAPER_EXECUTIVE;
-  if (strcmp (format, "iso_a2") == 0)
-    return DMPAPER_A2;
-  if (strcmp (format, "iso_a3") == 0)
-    return DMPAPER_A3;
-  if (strcmp (format, "iso_a4") == 0)
-    return DMPAPER_A4;
-  if (strcmp (format, "iso_a5") == 0)
-    return DMPAPER_A5;
-  if (strcmp (format, "iso_b4") == 0)
-    return DMPAPER_B4;
-  if (strcmp (format, "iso_b5") == 0)
-    return DMPAPER_B5;
-  if (strcmp (format, "na_quarto") == 0)
-    return DMPAPER_QUARTO;
-  if (strcmp (format, "na_10x14") == 0)
-    return DMPAPER_10X14;
-  if (strcmp (format, "na_number-9") == 0)
-    return DMPAPER_ENV_9;
-  if (strcmp (format, "na_number-10") == 0)
-    return DMPAPER_ENV_10;
-  if (strcmp (format, "na_number-11") == 0)
-    return DMPAPER_ENV_11;
-  if (strcmp (format, "na_number-12") == 0)
-    return DMPAPER_ENV_12;
-  if (strcmp (format, "na_number-14") == 0)
-    return DMPAPER_ENV_14;
-  if (strcmp (format, "na_c") == 0)
-    return DMPAPER_CSHEET;
-  if (strcmp (format, "na_d") == 0)
-    return DMPAPER_DSHEET;
-  if (strcmp (format, "na_e") == 0)
-    return DMPAPER_ESHEET;
-  if (strcmp (format, "iso_dl") == 0)
-    return DMPAPER_ENV_DL;
-  if (strcmp (format, "iso_c3") == 0)
-    return DMPAPER_ENV_C3;
-  if (strcmp (format, "iso_c4") == 0)
-    return DMPAPER_ENV_C4;
-  if (strcmp (format, "iso_c5") == 0)
-    return DMPAPER_ENV_C5;
-  if (strcmp (format, "iso_c6") == 0)
-    return DMPAPER_ENV_C6;
-  if (strcmp (format, "iso_c5c6") == 0)
-    return DMPAPER_ENV_C65;
-  if (strcmp (format, "iso_b6") == 0)
-    return DMPAPER_ENV_B6;
-  if (strcmp (format, "om_italian") == 0)
-    return DMPAPER_ENV_ITALY;
-  if (strcmp (format, "na_monarch") == 0)
-    return DMPAPER_ENV_MONARCH;
-  if (strcmp (format, "na_personal") == 0)
-    return DMPAPER_ENV_PERSONAL;
-  if (strcmp (format, "na_fanfold-us") == 0)
-    return DMPAPER_FANFOLD_US;
-  if (strcmp (format, "na_fanfold-eur") == 0)
-    return DMPAPER_FANFOLD_STD_GERMAN;
-  if (strcmp (format, "na_foolscap") == 0)
-    return DMPAPER_FANFOLD_LGL_GERMAN;
-  if (strcmp (format, "jpn_hagaki") == 0)
-    return DMPAPER_JAPANESE_POSTCARD;
-  if (strcmp (format, "na_9x11") == 0)
-    return DMPAPER_9X11;
-  if (strcmp (format, "na_10x11") == 0)
-    return DMPAPER_10X11;
-  if (strcmp (format, "om_invite") == 0)
-    return DMPAPER_ENV_INVITE;
-  if (strcmp (format, "na_letter-extra") == 0)
-    return DMPAPER_LETTER_EXTRA;
-  if (strcmp (format, "na_legal-extra") == 0)
-    return DMPAPER_LEGAL_EXTRA;
-  if (strcmp (format, "na_arch") == 0)
-    return DMPAPER_TABLOID_EXTRA;
-  if (strcmp (format, "iso_a3-extra") == 0)
-    return DMPAPER_A3_EXTRA;
-  if (strcmp (format, "iso_a4-extra") == 0)
-    return DMPAPER_A4_EXTRA;
-  if (strcmp (format, "iso_a5-extra") == 0)
-    return DMPAPER_A5_EXTRA;
-  if (strcmp (format, "iso_b5-extra") == 0)
-    return DMPAPER_B5_EXTRA;
-  if (strcmp (format, "na_b-plus") == 0)
-    return DMPAPER_B_PLUS;
-  if (strcmp (format, "na_letter-plus") == 0)
-    return DMPAPER_LETTER_PLUS;
-
-  return 0;
-}
-
-static char *
-get_default_printer (void)
-{
-  wchar_t *win32_printer_name = NULL;
-  char *printer_name = NULL;
-  DWORD needed;
-
-  GetDefaultPrinterW (NULL, &needed);
-  win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
-  if (!GetDefaultPrinterW (win32_printer_name, &needed))
-    {
-      g_free (win32_printer_name);
-      return NULL;
-    }
-  printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
-  g_free (win32_printer_name);
-
-  return printer_name;
-}
-
-static void
-set_hard_margins (GtkPrintOperation *op)
-{
-  double top, bottom, left, right;
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-
-  top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
-  bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
-      - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
-  left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
-  right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
-      - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
-
-  _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
-}
-
-void
-win32_start_page (GtkPrintOperation *op,
-                 GtkPrintContext *print_context,
-                 GtkPageSetup *page_setup)
-{
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-  LPDEVMODEW devmode;
-  GtkPaperSize *paper_size;
-  double x_off, y_off;
-
-  devmode = GlobalLock (op_win32->devmode);
-  
-  devmode->dmFields |= DM_ORIENTATION;
-  devmode->dmOrientation =
-    orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
-  
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-  devmode->dmFields |= DM_PAPERSIZE;
-  devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
-  devmode->dmPaperSize = paper_size_to_win32 (paper_size);
-  if (devmode->dmPaperSize == 0)
-    {
-      devmode->dmPaperSize = DMPAPER_USER;
-      devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
-
-      /* Lengths in DEVMODE are in tenths of a millimeter */
-      devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
-      devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
-    }
-  
-  ResetDCW (op_win32->hdc, devmode);
-  
-  GlobalUnlock (op_win32->devmode);
-
-  set_hard_margins (op);
-  x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
-  y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
-  cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
-  
-  StartPage (op_win32->hdc);
-}
-
-static void
-win32_end_page (GtkPrintOperation *op,
-               GtkPrintContext *print_context)
-{
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-
-  cairo_surface_show_page (op_win32->surface);
-
-  EndPage (op_win32->hdc);
-}
-
-static gboolean
-win32_poll_status_timeout (GtkPrintOperation *op)
-{
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-  
-  op_win32->timeout_id = 0;
-  /* We need to ref this, as setting the status to finished
-     might unref the object */
-  g_object_ref (op);
-  win32_poll_status (op);
-
-  if (!gtk_print_operation_is_finished (op)) {
-    op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
-                                         (GSourceFunc)win32_poll_status_timeout,
-                                         op);
-    gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
-  }
-  g_object_unref (op);
-  return FALSE;
-}
-
-
-static void
-win32_end_run (GtkPrintOperation *op,
-              gboolean           wait,
-              gboolean           cancelled)
-{
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-  LPDEVNAMES devnames;
-  HANDLE printerHandle = 0;
-
-  cairo_surface_finish (op_win32->surface);
-  
-  EndDoc (op_win32->hdc);
-
-  if (op->priv->track_print_status)
-    {
-      devnames = GlobalLock (op_win32->devnames);
-      if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
-                        &printerHandle, NULL))
-       printerHandle = 0;
-      GlobalUnlock (op_win32->devnames);
-    }
-  
-  GlobalFree (op_win32->devmode);
-  GlobalFree (op_win32->devnames);
-
-  cairo_surface_destroy (op_win32->surface);
-  op_win32->surface = NULL;
-
-  DeleteDC (op_win32->hdc);
-  
-  if (printerHandle != 0)
-    {
-      op_win32->printerHandle = printerHandle;
-      win32_poll_status (op);
-      op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
-                                           (GSourceFunc)win32_poll_status_timeout,
-                                           op);
-      gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
-    }
-  else
-    /* Dunno what happened, pretend its finished */
-    _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
-}
-
-static void
-win32_poll_status (GtkPrintOperation *op)
-{
-  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
-  guchar *data;
-  DWORD needed;
-  JOB_INFO_1W *job_info;
-  GtkPrintStatus status;
-  char *status_str;
-  BOOL ret;
-
-  GetJobW (op_win32->printerHandle, op_win32->job_id,
-          1,(LPBYTE)NULL, 0, &needed);
-  data = g_malloc (needed);
-  ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
-                1, (LPBYTE)data, needed, &needed);
-
-  status_str = NULL;
-  if (ret)
-    {
-      DWORD win32_status;
-      job_info = (JOB_INFO_1W *)data;
-      win32_status = job_info->Status;
-
-      if (job_info->pStatus)
-       status_str = g_utf16_to_utf8 (job_info->pStatus, 
-                                     -1, NULL, NULL, NULL);
-     
-      if (win32_status &
-         (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
-       status = GTK_PRINT_STATUS_FINISHED;
-      else if (win32_status &
-              (JOB_STATUS_OFFLINE |
-               JOB_STATUS_PAPEROUT |
-               JOB_STATUS_PAUSED |
-               JOB_STATUS_USER_INTERVENTION))
-       {
-         status = GTK_PRINT_STATUS_PENDING_ISSUE;
-         if (status_str == NULL)
-           {
-             if (win32_status & JOB_STATUS_OFFLINE)
-               status_str = g_strdup (_("Printer offline"));
-             else if (win32_status & JOB_STATUS_PAPEROUT)
-               status_str = g_strdup (_("Out of paper"));
-             else if (win32_status & JOB_STATUS_PAUSED)
-               status_str = g_strdup (_("Paused"));
-             else if (win32_status & JOB_STATUS_USER_INTERVENTION)
-               status_str = g_strdup (_("Need user intervention"));
-           }
-       }
-      else if (win32_status &
-              (JOB_STATUS_BLOCKED_DEVQ |
-               JOB_STATUS_DELETED |
-               JOB_STATUS_ERROR))
-       status = GTK_PRINT_STATUS_FINISHED_ABORTED;
-      else if (win32_status &
-              (JOB_STATUS_SPOOLING |
-               JOB_STATUS_DELETING))
-       status = GTK_PRINT_STATUS_PENDING;
-      else if (win32_status & JOB_STATUS_PRINTING)
-       status = GTK_PRINT_STATUS_PRINTING;
-      else
-       status = GTK_PRINT_STATUS_FINISHED;
-    }
-  else
-    status = GTK_PRINT_STATUS_FINISHED;
-
-  g_free (data);
-
-  _gtk_print_operation_set_status (op, status, status_str);
-  g_free (status_str);
-}
-
-static void
-op_win32_free (GtkPrintOperationWin32 *op_win32)
-{
-  if (op_win32->printerHandle)
-    ClosePrinter (op_win32->printerHandle);
-  if (op_win32->timeout_id != 0)
-    g_source_remove (op_win32->timeout_id);
-  g_free (op_win32);
-}
-
-static HWND
-get_parent_hwnd (GtkWidget *widget)
-{
-  GtkNative *native;
-
-  native = gtk_widget_get_native (widget);
-  gtk_widget_realize (GTK_WIDGET (native));
-  return gdk_win32_surface_get_handle (gtk_native_get_surface (native));
-}
-
-static void
-devnames_to_settings (GtkPrintSettings *settings,
-                     HANDLE hDevNames)
-{
-  GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
-  gtk_print_settings_set_printer (settings, devnames->device);
-  gtk_print_win32_devnames_free (devnames);
-}
-
-static void
-devmode_to_settings (GtkPrintSettings *settings,
-                    HANDLE hDevMode)
-{
-  LPDEVMODEW devmode;
-
-  devmode = GlobalLock (hDevMode);
-  
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
-                             devmode->dmDriverVersion);
-  if (devmode->dmDriverExtra != 0)
-    {
-      char *extra = g_base64_encode (((const guchar *)devmode) + sizeof (DEVMODEW),
-                                    devmode->dmDriverExtra);
-      gtk_print_settings_set (settings,
-                             GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
-                             extra);
-      g_free (extra);
-    }
-  
-  char *devmode_name = g_utf16_to_utf8 (devmode->dmDeviceName, -1, NULL, NULL, NULL);
-  gtk_print_settings_set (settings, "win32-devmode-name", devmode_name);
-  g_free (devmode_name);
-
-  if (devmode->dmFields & DM_ORIENTATION)
-    gtk_print_settings_set_orientation (settings,
-                                       orientation_from_win32 (devmode->dmOrientation));
-  
-  
-  if (devmode->dmFields & DM_PAPERSIZE &&
-      devmode->dmPaperSize != 0)
-    {
-      GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
-      if (paper_size)
-       {
-         gtk_print_settings_set_paper_size (settings, paper_size);
-         gtk_paper_size_free (paper_size);
-       }
-      gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
-    }
-  else if ((devmode->dmFields & DM_PAPERSIZE &&
-           devmode->dmPaperSize == 0) ||
-          ((devmode->dmFields & DM_PAPERWIDTH) &&
-           (devmode->dmFields & DM_PAPERLENGTH)))
-    {
-      GtkPaperSize *paper_size;
-      char *form_name = NULL;
-      if (devmode->dmFields & DM_FORMNAME)
-       form_name = g_utf16_to_utf8 (devmode->dmFormName, 
-                                    -1, NULL, NULL, NULL);
-      if (form_name == NULL || form_name[0] == 0)
-       form_name = g_strdup (_("Custom size"));
-
-      /* Lengths in DEVMODE are in tenths of a millimeter */
-      paper_size = gtk_paper_size_new_custom (form_name,
-                                             form_name,
-                                             devmode->dmPaperWidth / 10.0,
-                                             devmode->dmPaperLength / 10.0,
-                                             GTK_UNIT_MM);
-      gtk_print_settings_set_paper_size (settings, paper_size);
-      gtk_paper_size_free (paper_size);
-    }
-  
-  if (devmode->dmFields & DM_SCALE)
-    gtk_print_settings_set_scale (settings, devmode->dmScale);
-  
-  if (devmode->dmFields & DM_COPIES)
-    gtk_print_settings_set_n_copies (settings,
-                                    devmode->dmCopies);
-  
-  if (devmode->dmFields & DM_DEFAULTSOURCE)
-    {
-      const char *source;
-      switch (devmode->dmDefaultSource)
-       {
-       default:
-       case DMBIN_AUTO:
-         source = "auto";
-         break;
-       case DMBIN_CASSETTE:
-         source = "cassette";
-         break;
-       case DMBIN_ENVELOPE:
-         source = "envelope";
-         break;
-       case DMBIN_ENVMANUAL:
-         source = "envelope-manual";
-         break;
-       case DMBIN_LOWER:
-         source = "lower";
-         break;
-       case DMBIN_MANUAL:
-         source = "manual";
-         break;
-       case DMBIN_MIDDLE:
-         source = "middle";
-         break;
-       case DMBIN_ONLYONE:
-         source = "only-one";
-         break;
-       case DMBIN_FORMSOURCE:
-         source = "form-source";
-         break;
-       case DMBIN_LARGECAPACITY:
-         source = "large-capacity";
-         break;
-       case DMBIN_LARGEFMT:
-         source = "large-format";
-         break;
-       case DMBIN_TRACTOR:
-         source = "tractor";
-         break;
-       case DMBIN_SMALLFMT:
-         source = "small-format";
-         break;
-       }
-      gtk_print_settings_set_default_source (settings, source);
-      gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
-    }
-  
-  if (devmode->dmFields & DM_PRINTQUALITY)
-    {
-      GtkPrintQuality quality;
-      switch (devmode->dmPrintQuality)
-       {
-       case DMRES_LOW:
-         quality = GTK_PRINT_QUALITY_LOW;
-         break;
-       case DMRES_MEDIUM:
-         quality = GTK_PRINT_QUALITY_NORMAL;
-         break;
-       default:
-       case DMRES_HIGH:
-         quality = GTK_PRINT_QUALITY_HIGH;
-         break;
-       case DMRES_DRAFT:
-         quality = GTK_PRINT_QUALITY_DRAFT;
-         break;
-       }
-      gtk_print_settings_set_quality (settings, quality);
-      gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
-    }
-  
-  if (devmode->dmFields & DM_COLOR)
-    gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
-  
-  if (devmode->dmFields & DM_DUPLEX)
-    {
-      GtkPrintDuplex duplex;
-      switch (devmode->dmDuplex)
-       {
-       default:
-       case DMDUP_SIMPLEX:
-         duplex = GTK_PRINT_DUPLEX_SIMPLEX;
-         break;
-       case DMDUP_HORIZONTAL:
-         duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
-         break;
-       case DMDUP_VERTICAL:
-         duplex = GTK_PRINT_DUPLEX_VERTICAL;
-         break;
-       }
-      
-      gtk_print_settings_set_duplex (settings, duplex);
-    }
-  
-  if (devmode->dmFields & DM_COLLATE)
-    gtk_print_settings_set_collate (settings,
-                                   devmode->dmCollate == DMCOLLATE_TRUE);
-  
-  if (devmode->dmFields & DM_MEDIATYPE)
-    {
-      const char *media_type;
-      switch (devmode->dmMediaType)
-       {
-       default:
-       case DMMEDIA_STANDARD:
-         media_type = "stationery";
-         break;
-       case DMMEDIA_TRANSPARENCY:
-         media_type = "transparency";
-         break;
-       case DMMEDIA_GLOSSY:
-         media_type = "photographic-glossy";
-         break;
-       }
-      gtk_print_settings_set_media_type (settings, media_type);
-      gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
-    }
-  
-  if (devmode->dmFields & DM_DITHERTYPE)
-    {
-      const char *dither;
-      switch (devmode->dmDitherType)
-       {
-       default:
-       case DMDITHER_FINE:
-         dither = "fine";
-         break;
-       case DMDITHER_NONE:
-         dither = "none";
-         break;
-       case DMDITHER_COARSE:
-         dither = "coarse";
-         break;
-       case DMDITHER_LINEART:
-         dither = "lineart";
-         break;
-       case DMDITHER_GRAYSCALE:
-         dither = "grayscale";
-         break;
-       case DMDITHER_ERRORDIFFUSION:
-         dither = "error-diffusion";
-         break;
-       }
-      gtk_print_settings_set_dither (settings, dither);
-      gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
-    }
-  
-  GlobalUnlock (hDevMode);
-}
-
-static void
-dialog_to_print_settings (GtkPrintOperation *op,
-                         LPPRINTDLGEXW printdlgex)
-{
-  guint i;
-  GtkPrintSettings *settings;
-
-  settings = gtk_print_settings_new ();
-
-  gtk_print_settings_set_print_pages (settings,
-                                     GTK_PRINT_PAGES_ALL);
-  if (printdlgex->Flags & PD_CURRENTPAGE)
-    gtk_print_settings_set_print_pages (settings,
-                                       GTK_PRINT_PAGES_CURRENT);
-  else if (printdlgex->Flags & PD_PAGENUMS)
-    gtk_print_settings_set_print_pages (settings,
-                                       GTK_PRINT_PAGES_RANGES);
-
-  if (printdlgex->nPageRanges > 0)
-    {
-      GtkPageRange *ranges;
-      ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
-
-      for (i = 0; i < printdlgex->nPageRanges; i++)
-       {
-         ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
-         ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
-       }
-
-      gtk_print_settings_set_page_ranges (settings, ranges,
-                                         printdlgex->nPageRanges);
-      g_free (ranges);
-    }
-  
-  if (printdlgex->hDevNames != NULL)
-    devnames_to_settings (settings, printdlgex->hDevNames);
-
-  if (printdlgex->hDevMode != NULL)
-    devmode_to_settings (settings, printdlgex->hDevMode);
-  
-  gtk_print_operation_set_print_settings (op, settings);
-}
-
-static HANDLE
-devmode_from_settings (GtkPrintSettings *settings,
-                      GtkPageSetup *page_setup,
-                      HANDLE hDevModeParam)
-{
-  HANDLE hDevMode = hDevModeParam;
-  LPDEVMODEW devmode;
-  guchar *extras;
-  GtkPaperSize *paper_size;
-  const char *extras_base64;
-  gsize extras_len;
-  const char *val;
-
-  /* If we already provided a valid hDevMode, don't initialize a new one; just lock the one we have */
-  if (hDevMode)
-    {
-      devmode = GlobalLock (hDevMode);
-    }
-  else
-    {
-      extras = NULL;
-      extras_len = 0;
-      extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
-      if (extras_base64)
-        extras = g_base64_decode (extras_base64, &extras_len);
-  
-      hDevMode = GlobalAlloc (GMEM_MOVEABLE, 
-                             sizeof (DEVMODEW) + extras_len);
-
-      devmode = GlobalLock (hDevMode);
-
-      memset (devmode, 0, sizeof (DEVMODEW));
-  
-      devmode->dmSpecVersion = DM_SPECVERSION;
-      devmode->dmSize = sizeof (DEVMODEW);
-  
-      gunichar2 *device_name = g_utf8_to_utf16 (gtk_print_settings_get (settings, "win32-devmode-name"), -1, NULL, NULL, NULL);
-      memcpy (devmode->dmDeviceName, device_name, CCHDEVICENAME);
-      g_free (device_name);
-
-
-      devmode->dmDriverExtra = 0;
-      if (extras && extras_len > 0)
-        {
-          devmode->dmDriverExtra = extras_len;
-          memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
-        }
-      g_free (extras);
-  
-      if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
-        {
-          devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
-        }
-    }
-  
-  if (page_setup ||
-      gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
-    {
-      GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
-      if (page_setup)
-       orientation = gtk_page_setup_get_orientation (page_setup);
-      devmode->dmFields |= DM_ORIENTATION;
-      devmode->dmOrientation = orientation_to_win32 (orientation);
-    }
-
-  if (page_setup)
-    paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
-  else
-    {
-      int size;
-      if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
-         (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
-       {
-         devmode->dmFields |= DM_PAPERSIZE;
-         devmode->dmPaperSize = size;
-         paper_size = NULL;
-       }
-      else
-       paper_size = gtk_print_settings_get_paper_size (settings);
-    }
-  if (paper_size)
-    {
-      devmode->dmFields |= DM_PAPERSIZE;
-      devmode->dmPaperSize = paper_size_to_win32 (paper_size);
-      if (devmode->dmPaperSize == 0)
-       {
-         devmode->dmPaperSize = DMPAPER_USER;
-         devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
-
-          /* Lengths in DEVMODE are in tenths of a millimeter */
-         devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
-         devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
-       }
-      gtk_paper_size_free (paper_size);
-    }
-
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
-    {
-      devmode->dmFields |= DM_SCALE;
-      devmode->dmScale = gtk_print_settings_get_scale (settings);
-    }
-  
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
-    {
-      devmode->dmFields |= DM_COPIES;
-      devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
-    }
-
-  if (gtk_print_settings_has_key (settings, "win32-default-source"))
-    {
-      devmode->dmFields |= DM_DEFAULTSOURCE;
-      devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
-    }
-  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
-    {
-      devmode->dmFields |= DM_DEFAULTSOURCE;
-      devmode->dmDefaultSource = DMBIN_AUTO;
-
-      val = gtk_print_settings_get_default_source (settings);
-      if (strcmp (val, "auto") == 0)
-       devmode->dmDefaultSource = DMBIN_AUTO;
-      if (strcmp (val, "cassette") == 0)
-       devmode->dmDefaultSource = DMBIN_CASSETTE;
-      if (strcmp (val, "envelope") == 0)
-       devmode->dmDefaultSource = DMBIN_ENVELOPE;
-      if (strcmp (val, "envelope-manual") == 0)
-       devmode->dmDefaultSource = DMBIN_ENVMANUAL;
-      if (strcmp (val, "lower") == 0)
-       devmode->dmDefaultSource = DMBIN_LOWER;
-      if (strcmp (val, "manual") == 0)
-       devmode->dmDefaultSource = DMBIN_MANUAL;
-      if (strcmp (val, "middle") == 0)
-       devmode->dmDefaultSource = DMBIN_MIDDLE;
-      if (strcmp (val, "only-one") == 0)
-       devmode->dmDefaultSource = DMBIN_ONLYONE;
-      if (strcmp (val, "form-source") == 0)
-       devmode->dmDefaultSource = DMBIN_FORMSOURCE;
-      if (strcmp (val, "large-capacity") == 0)
-       devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
-      if (strcmp (val, "large-format") == 0)
-       devmode->dmDefaultSource = DMBIN_LARGEFMT;
-      if (strcmp (val, "tractor") == 0)
-       devmode->dmDefaultSource = DMBIN_TRACTOR;
-      if (strcmp (val, "small-format") == 0)
-       devmode->dmDefaultSource = DMBIN_SMALLFMT;
-    }
-
-  if (gtk_print_settings_has_key (settings, "win32-print-quality"))
-    {
-      devmode->dmFields |= DM_PRINTQUALITY;
-      devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
-    }
-  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
-    {
-      devmode->dmFields |= DM_PRINTQUALITY;
-      devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
-    } 
-  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
-    {
-      devmode->dmFields |= DM_PRINTQUALITY;
-      switch (gtk_print_settings_get_quality (settings))
-       {
-       case GTK_PRINT_QUALITY_LOW:
-         devmode->dmPrintQuality = DMRES_LOW;
-         break;
-       case GTK_PRINT_QUALITY_DRAFT:
-         devmode->dmPrintQuality = DMRES_DRAFT;
-         break;
-       default:
-       case GTK_PRINT_QUALITY_NORMAL:
-         devmode->dmPrintQuality = DMRES_MEDIUM;
-         break;
-       case GTK_PRINT_QUALITY_HIGH:
-         devmode->dmPrintQuality = DMRES_HIGH;
-         break;
-       }
-    }
-
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
-    {
-      devmode->dmFields |= DM_COLOR;
-      if (gtk_print_settings_get_use_color (settings))
-       devmode->dmColor = DMCOLOR_COLOR;
-      else
-       devmode->dmColor = DMCOLOR_MONOCHROME;
-    }
-
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
-    {
-      devmode->dmFields |= DM_DUPLEX;
-      switch (gtk_print_settings_get_duplex (settings))
-       {
-       default:
-       case GTK_PRINT_DUPLEX_SIMPLEX:
-         devmode->dmDuplex = DMDUP_SIMPLEX;
-         break;
-       case GTK_PRINT_DUPLEX_HORIZONTAL:
-         devmode->dmDuplex = DMDUP_HORIZONTAL;
-         break;
-       case GTK_PRINT_DUPLEX_VERTICAL:
-         devmode->dmDuplex = DMDUP_VERTICAL;
-         break;
-       }
-    }
-
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
-    {
-      devmode->dmFields |= DM_COLLATE;
-      if (gtk_print_settings_get_collate (settings))
-       devmode->dmCollate = DMCOLLATE_TRUE;
-      else
-       devmode->dmCollate = DMCOLLATE_FALSE;
-    }
-
-  if (gtk_print_settings_has_key (settings, "win32-media-type"))
-    {
-      devmode->dmFields |= DM_MEDIATYPE;
-      devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
-    }
-  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
-    {
-      devmode->dmFields |= DM_MEDIATYPE;
-      devmode->dmMediaType = DMMEDIA_STANDARD;
-      
-      val = gtk_print_settings_get_media_type (settings);
-      if (strcmp (val, "transparency") == 0)
-       devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
-      if (strcmp (val, "photographic-glossy") == 0)
-       devmode->dmMediaType = DMMEDIA_GLOSSY;
-    }
-  if (gtk_print_settings_has_key (settings, "win32-dither-type"))
-    {
-      devmode->dmFields |= DM_DITHERTYPE;
-      devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
-    }
-  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
-    {
-      devmode->dmFields |= DM_DITHERTYPE;
-      devmode->dmDitherType = DMDITHER_FINE;
-      
-      val = gtk_print_settings_get_dither (settings);
-      if (strcmp (val, "none") == 0)
-       devmode->dmDitherType = DMDITHER_NONE;
-      if (strcmp (val, "coarse") == 0)
-       devmode->dmDitherType = DMDITHER_COARSE;
-      if (strcmp (val, "fine") == 0)
-       devmode->dmDitherType = DMDITHER_FINE;
-      if (strcmp (val, "lineart") == 0)
-       devmode->dmDitherType = DMDITHER_LINEART;
-      if (strcmp (val, "grayscale") == 0)
-       devmode->dmDitherType = DMDITHER_GRAYSCALE;
-      if (strcmp (val, "error-diffusion") == 0)
-       devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
-    }
-  
-  GlobalUnlock (hDevMode);
-
-  return hDevMode;
-}
-
-static void
-dialog_from_print_settings (GtkPrintOperation *op,
-                           LPPRINTDLGEXW printdlgex)
-{
-  GtkPrintSettings *settings = op->priv->print_settings;
-  const char *printer;
-
-  if (settings == NULL)
-    return;
-
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
-    {
-      GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
-
-      switch (print_pages)
-       {
-       default:
-       case GTK_PRINT_PAGES_SELECTION:
-       case GTK_PRINT_PAGES_ALL:
-         printdlgex->Flags |= PD_ALLPAGES;
-         break;
-       case GTK_PRINT_PAGES_CURRENT:
-         printdlgex->Flags |= PD_CURRENTPAGE;
-         break;
-       case GTK_PRINT_PAGES_RANGES:
-         printdlgex->Flags |= PD_PAGENUMS;
-         break;
-       }
-    }
-  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
-    {
-      GtkPageRange *ranges;
-      int num_ranges, i;
-
-      ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
-
-      if (num_ranges > MAX_PAGE_RANGES)
-       num_ranges = MAX_PAGE_RANGES;
-
-      printdlgex->nPageRanges = num_ranges;
-      for (i = 0; i < num_ranges; i++)
-       {
-         printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
-         printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
-       }
-    }
-  
-  /* If we have a printer saved, restore our settings */
-  printer = gtk_print_settings_get_printer (settings);
-  if (printer)
-    {
-      printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
-  
-      printdlgex->hDevMode = devmode_from_settings (settings,
-                                                 op->priv->default_page_setup, NULL);
-    }
-  else
-    {
-      /* Otherwise, use the default settings */
-      DWORD FlagsCopy = printdlgex->Flags;
-      printdlgex->Flags |= PD_RETURNDEFAULT;
-      PrintDlgExW (printdlgex);
-      printdlgex->Flags = FlagsCopy;
-
-      devmode_from_settings (settings, op->priv->default_page_setup, printdlgex->hDevMode);
-    }
-}
-
-typedef struct {
-  IPrintDialogCallback iPrintDialogCallback;
-  gboolean set_hwnd;
-  int ref_count;
-} PrintDialogCallback;
-
-
-static ULONG STDMETHODCALLTYPE
-iprintdialogcallback_addref (IPrintDialogCallback *This)
-{
-  PrintDialogCallback *callback = (PrintDialogCallback *)This;
-  return ++callback->ref_count;
-}
-
-static ULONG STDMETHODCALLTYPE
-iprintdialogcallback_release (IPrintDialogCallback *This)
-{
-  PrintDialogCallback *callback = (PrintDialogCallback *)This;
-  int ref_count = --callback->ref_count;
-
-  if (ref_count == 0)
-    g_free (This);
-
-  return ref_count;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
-                                    REFIID       riid,
-                                    LPVOID      *ppvObject)
-{
-   if (IsEqualIID (riid, &IID_IUnknown) ||
-       IsEqualIID (riid, &myIID_IPrintDialogCallback))
-     {
-       *ppvObject = This;
-       IUnknown_AddRef ((IUnknown *)This);
-       return NOERROR;
-     }
-   else
-     {
-       *ppvObject = NULL;
-       return E_NOINTERFACE;
-     }
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_initdone (IPrintDialogCallback *This)
-{
-  return S_FALSE;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
-{
-  return S_FALSE;
-}
-
-static HRESULT STDMETHODCALLTYPE
-iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
-                                   HWND hDlg,
-                                   UINT uMsg,
-                                   WPARAM wParam,
-                                   LPARAM lParam,
-                                   LRESULT *pResult)
-{
-  PrintDialogCallback *callback = (PrintDialogCallback *)This;
-
-  if (!callback->set_hwnd)
-    {
-      gdk_win32_set_modal_dialog_libgtk_only (hDlg);
-      callback->set_hwnd = TRUE;
-      while (g_main_context_pending (NULL))
-        g_main_context_iteration (NULL, TRUE);
-    }
-  else if (uMsg == got_gdk_events_message)
-    {
-      while (g_main_context_pending (NULL))
-        g_main_context_iteration (NULL, TRUE);
-      *pResult = TRUE;
-      return S_OK;
-    }
-  
-  *pResult = 0;
-  return S_FALSE;
-}
-
-static IPrintDialogCallbackVtbl ipdc_vtbl = {
-  iprintdialogcallback_queryinterface,
-  iprintdialogcallback_addref,
-  iprintdialogcallback_release,
-  iprintdialogcallback_initdone,
-  iprintdialogcallback_selectionchange,
-  iprintdialogcallback_handlemessage
-};
-
-static IPrintDialogCallback *
-print_callback_new  (void)
-{
-  PrintDialogCallback *callback;
-
-  callback = g_new0 (PrintDialogCallback, 1);
-  callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
-  callback->ref_count = 1;
-  callback->set_hwnd = FALSE;
-
-  return &callback->iPrintDialogCallback;
-}
-
-static INT_PTR CALLBACK
-pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
-  GtkPrintOperation *op;
-  GtkPrintOperationWin32 *op_win32;
-  
-  if (message == WM_INITDIALOG)
-    {
-      PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
-      GtkWidget *plug;
-
-      op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
-      op_win32 = op->priv->platform_data;
-      plug = g_object_new(GTK_TYPE_WIDGET, NULL);
-
-      SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
-
-      gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
-      op_win32->embed_widget = plug;
-      gtk_box_append (GTK_BOX (plug), op->priv->custom_widget);
-      gtk_widget_set_visible (op->priv->custom_widget, TRUE);
-      gtk_widget_set_visible (plug, TRUE);
-
-      /* This dialog is modal, so we grab the embed widget */
-      gtk_grab_add (plug);
-      return FALSE;
-    }
-  else if (message == WM_DESTROY)
-    {
-      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
-      op_win32 = op->priv->platform_data;
-      
-      g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
-      g_object_unref (g_object_ref_sink (op_win32->embed_widget));
-      op_win32->embed_widget = NULL;
-      op->priv->custom_widget = NULL;
-    }
-  else 
-    {
-      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
-      op_win32 = op->priv->platform_data;
-
-      /* TODO: We don't have GtkWin32EmbedWidgets anymore, but it is not currently clear
-       *       at this point what will be the proper replacement for this.  For now,
-       *       do the message handling that was in _gtk_win32_embed_widget_dialog_procedure ()
-       *       here and fill in the rest when things become clearer.
-       */
-      if (message == WM_SIZE)
-        {
-          gtk_widget_queue_resize (op_win32->embed_widget);
-    }
-
-      return FALSE;
-    }
-  
-  return FALSE;
-}
-
-static HPROPSHEETPAGE
-create_application_page (GtkPrintOperation *op)
-{
-  HPROPSHEETPAGE hpage;
-  PROPSHEETPAGEW page;
-  DLGTEMPLATE *template;
-  HGLOBAL htemplate;
-  LONG base_units;
-  WORD baseunitX, baseunitY;
-  WORD *array;
-  GtkRequisition requisition;
-  const char *tab_label;
-
-  /* Make the template the size of the custom widget size request */
-  gtk_widget_get_preferred_size (op->priv->custom_widget,
-                                 &requisition, NULL);
-
-  base_units = GetDialogBaseUnits ();
-  baseunitX = LOWORD (base_units);
-  baseunitY = HIWORD (base_units);
-  
-  htemplate = GlobalAlloc (GMEM_MOVEABLE, 
-                          sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
-  template = GlobalLock (htemplate);
-  template->style = WS_CHILDWINDOW | DS_CONTROL;
-  template->dwExtendedStyle = WS_EX_CONTROLPARENT;
-  template->cdit = 0;
-  template->x = MulDiv (0, 4, baseunitX);
-  template->y = MulDiv (0, 8, baseunitY);
-  template->cx = MulDiv (requisition.width, 4, baseunitX);
-  template->cy = MulDiv (requisition.height, 8, baseunitY);
-  
-  array = (WORD *) (template+1);
-  *array++ = 0; /* menu */
-  *array++ = 0; /* class */
-  *array++ = 0; /* title */
-  
-  memset (&page, 0, sizeof (page));
-  page.dwSize = sizeof (page);
-  page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
-  page.hInstance = NULL;
-  page.pResource = template;
-  
-  tab_label = op->priv->custom_tab_label;
-  if (tab_label == NULL)
-    tab_label = g_get_application_name ();
-  if (tab_label == NULL)
-    tab_label = _("Application");
-  page.pszTitle = g_utf8_to_utf16 (tab_label, 
-                                  -1, NULL, NULL, NULL);
-  page.pfnDlgProc = pageDlgProc;
-  page.pfnCallback = NULL;
-  page.lParam = (LPARAM) op;
-  hpage = CreatePropertySheetPageW (&page);
-  
-  GlobalUnlock (htemplate);
-  
-  /* TODO: We're leaking htemplate here... */
-  
-  return hpage;
-}
-
-static GtkPageSetup *
-create_page_setup (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = op->priv;
-  GtkPageSetup *page_setup;
-  GtkPrintSettings *settings;
-  
-  if (priv->default_page_setup)
-    page_setup = gtk_page_setup_copy (priv->default_page_setup);
-  else
-    page_setup = gtk_page_setup_new ();
-
-  settings = priv->print_settings;
-  if (settings)
-    {
-      GtkPaperSize *paper_size;
-      
-      if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
-       gtk_page_setup_set_orientation (page_setup,
-                                       gtk_print_settings_get_orientation (settings));
-
-
-      paper_size = gtk_print_settings_get_paper_size (settings);
-      if (paper_size)
-       {
-         gtk_page_setup_set_paper_size (page_setup, paper_size);
-         gtk_paper_size_free (paper_size);
-       }
-
-      /* TODO: Margins? */
-    }
-  
-  return page_setup;
-}
-
-GtkPrintOperationResult
-gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
-                                       gboolean          *do_print)
-{
-  GtkPrintOperationResult result;
-  GtkPrintOperationWin32 *op_win32;
-  GtkPrintOperationPrivate *priv;
-  GtkPrintSettings *settings;
-  GtkPageSetup *page_setup;
-  DOCINFOW docinfo;
-  HGLOBAL hDevMode = NULL;
-  HGLOBAL hDevNames = NULL;
-  HDC hDC = NULL;
-  const char *printer = NULL;
-  double dpi_x, dpi_y;
-  int job_id;
-  cairo_t *cr;
-  DEVNAMES *pdn;
-  DEVMODEW *pdm;
-
-  *do_print = FALSE;
-
-  priv = op->priv;
-  settings = priv->print_settings;
-  
-  op_win32 = g_new0 (GtkPrintOperationWin32, 1);
-  priv->platform_data = op_win32;
-  priv->free_platform_data = (GDestroyNotify) op_win32_free;
-  printer = gtk_print_settings_get_printer (settings);
-
-  if (!printer)
-    {
-      /* No printer selected. Get the system default printer and store
-       * it in settings.
-       */
-      char *tmp_printer = get_default_printer ();
-      if (!tmp_printer)
-       {
-         result = GTK_PRINT_OPERATION_RESULT_ERROR;
-         g_set_error_literal (&priv->error,
-                              GTK_PRINT_ERROR,
-                              GTK_PRINT_ERROR_INTERNAL_ERROR,
-                              _("No printer found"));
-         goto out;
-       }
-      gtk_print_settings_set_printer (settings, tmp_printer);
-      printer = gtk_print_settings_get_printer (settings);
-      g_free (tmp_printer);
-    }
-
-  hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
-  hDevMode = devmode_from_settings (settings, op->priv->default_page_setup, NULL);
-
-  /* Create a printer DC for the print settings and page setup provided. */
-  pdn = GlobalLock (hDevNames);
-  pdm = GlobalLock (hDevMode);
-  hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
-                  (wchar_t*)pdn + pdn->wDeviceOffset,
-                  (wchar_t*)pdn + pdn->wOutputOffset,
-                  pdm );
-  GlobalUnlock (hDevNames);
-  GlobalUnlock (hDevMode);
-
-  if (!hDC)
-    {
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error_literal (&priv->error,
-                          GTK_PRINT_ERROR,
-                          GTK_PRINT_ERROR_INTERNAL_ERROR,
-                          _("Invalid argument to CreateDC"));
-      goto out;
-    }
-  
-  priv->print_context = _gtk_print_context_new (op);
-  page_setup = create_page_setup (op);
-  _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-  g_object_unref (page_setup);
-
-  *do_print = TRUE;
-
-  op_win32->surface = cairo_win32_printing_surface_create (hDC);
-  dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
-  dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
-
-  cr = cairo_create (op_win32->surface);
-  gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
-  cairo_destroy (cr);
-
-  set_hard_margins (op);
-
-  memset (&docinfo, 0, sizeof (DOCINFOW));
-  docinfo.cbSize = sizeof (DOCINFOW); 
-  docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
-  docinfo.lpszOutput = NULL; 
-  docinfo.lpszDatatype = NULL; 
-  docinfo.fwType = 0; 
-
-  job_id = StartDocW (hDC, &docinfo); 
-  g_free ((void *)docinfo.lpszDocName);
-  if (job_id <= 0)
-    { 
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error_literal (&priv->error,
-                          GTK_PRINT_ERROR,
-                          GTK_PRINT_ERROR_GENERAL,
-                          _("Error from StartDoc"));
-      *do_print = FALSE;
-      cairo_surface_destroy (op_win32->surface);
-      op_win32->surface = NULL;
-      goto out; 
-    }
-
-  result = GTK_PRINT_OPERATION_RESULT_APPLY;
-  op_win32->hdc = hDC;
-  op_win32->devmode = hDevMode;
-  op_win32->devnames = hDevNames;
-  op_win32->job_id = job_id;
-  op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
-  op->priv->num_page_ranges = 0;
-  if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
-    op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
-                                                               &op->priv->num_page_ranges);
-  op->priv->manual_num_copies = 1;
-  op->priv->manual_collation = FALSE;
-  op->priv->manual_reverse = FALSE;
-  op->priv->manual_orientation = FALSE;
-  op->priv->manual_scale = 1.0;
-  op->priv->manual_page_set = GTK_PAGE_SET_ALL;
-  op->priv->manual_number_up = 1;
-  op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-
-  op->priv->start_page = win32_start_page;
-  op->priv->end_page = win32_end_page;
-  op->priv->end_run = win32_end_run;
-  
- out:
-  if (!*do_print && hDC != NULL)
-    DeleteDC (hDC);
-
-  if (!*do_print && hDevMode != NULL)
-    GlobalFree (hDevMode);
-
-  if (!*do_print && hDevNames != NULL)
-    GlobalFree (hDevNames);
-
-  return result;
-}
-
-GtkPrintOperationResult
-gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
-                                    GtkWindow         *parent,
-                                    gboolean          *do_print)
-{
-  HRESULT hResult;
-  LPPRINTDLGEXW printdlgex = NULL;
-  LPPRINTPAGERANGE page_ranges = NULL;
-  HWND parentHWnd;
-  GtkWidget *invisible = NULL;
-  GtkPrintOperationResult result;
-  GtkPrintOperationWin32 *op_win32;
-  GtkPrintOperationPrivate *priv;
-  IPrintDialogCallback *callback;
-  HPROPSHEETPAGE prop_page;
-  static gsize common_controls_initialized = 0;
-
-  if (g_once_init_enter (&common_controls_initialized))
-    {
-      BOOL initialized;
-      INITCOMMONCONTROLSEX icc;
-
-      memset (&icc, 0, sizeof (icc));
-      icc.dwSize = sizeof (icc);
-      icc.dwICC = ICC_WIN95_CLASSES;
-
-      initialized = InitCommonControlsEx (&icc);
-      if (!initialized)
-        g_warning ("Failed to InitCommonControlsEx: %lu", GetLastError ());
-
-      _gtk_load_dll_with_libgtk3_manifest ("comdlg32.dll");
-
-      g_once_init_leave (&common_controls_initialized, initialized ? 1 : 0);
-    }
-  
-  *do_print = FALSE;
-
-  priv = op->priv;
-  
-  op_win32 = g_new0 (GtkPrintOperationWin32, 1);
-  priv->platform_data = op_win32;
-  priv->free_platform_data = (GDestroyNotify) op_win32_free;
-  
-  if (parent == NULL)
-    {
-      invisible = gtk_window_new ();
-      parentHWnd = get_parent_hwnd (invisible);
-    }
-  else
-    parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
-
-  printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
-  if (!printdlgex)
-    {
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error_literal (&priv->error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_NOMEM,
-                           _("Not enough free memory"));
-      goto out;
-    }      
-
-  printdlgex->lStructSize = sizeof (PRINTDLGEXW);
-  printdlgex->hwndOwner = parentHWnd;
-  printdlgex->hDevMode = NULL;
-  printdlgex->hDevNames = NULL;
-  printdlgex->hDC = NULL;
-  printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
-  if (op->priv->current_page == -1)
-    printdlgex->Flags |= PD_NOCURRENTPAGE;
-  printdlgex->Flags2 = 0;
-  printdlgex->ExclusionFlags = 0;
-
-  page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR, 
-                                               MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
-  if (!page_ranges) 
-    {
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error_literal (&priv->error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_NOMEM,
-                           _("Not enough free memory"));
-      goto out;
-    }
-
-  printdlgex->nPageRanges = 0;
-  printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
-  printdlgex->lpPageRanges = page_ranges;
-  printdlgex->nMinPage = 1;
-  if (op->priv->nr_of_pages != -1)
-    printdlgex->nMaxPage = op->priv->nr_of_pages;
-  else
-    printdlgex->nMaxPage = 10000;
-  printdlgex->nCopies = 1;
-  printdlgex->hInstance = 0;
-  printdlgex->lpPrintTemplateName = NULL;
-  printdlgex->lpCallback = NULL;
-
-  g_signal_emit_by_name (op, "create-custom-widget",
-                        &op->priv->custom_widget);
-  if (op->priv->custom_widget) {
-    prop_page = create_application_page (op);
-    printdlgex->nPropertyPages = 1;
-    printdlgex->lphPropertyPages = &prop_page;
-  } else {
-    printdlgex->nPropertyPages = 0;
-    printdlgex->lphPropertyPages = NULL;
-  }
-  
-  printdlgex->nStartPage = START_PAGE_GENERAL;
-  printdlgex->dwResultAction = 0;
-
-  dialog_from_print_settings (op, printdlgex);
-
-  callback = print_callback_new ();
-  printdlgex->lpCallback = (IUnknown *)callback;
-  got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
-
-  hResult = PrintDlgExW (printdlgex);
-  IUnknown_Release ((IUnknown *)callback);
-  gdk_win32_set_modal_dialog_libgtk_only (NULL);
-
-  if (hResult != S_OK) 
-    {
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      if (hResult == E_OUTOFMEMORY)
-       g_set_error_literal (&priv->error,
-                             GTK_PRINT_ERROR,
-                             GTK_PRINT_ERROR_NOMEM,
-                             _("Not enough free memory"));
-      else if (hResult == E_INVALIDARG)
-       g_set_error_literal (&priv->error,
-                             GTK_PRINT_ERROR,
-                             GTK_PRINT_ERROR_INTERNAL_ERROR,
-                             _("Invalid argument to PrintDlgEx"));
-      else if (hResult == E_POINTER)
-       g_set_error_literal (&priv->error,
-                             GTK_PRINT_ERROR,
-                             GTK_PRINT_ERROR_INTERNAL_ERROR,
-                             _("Invalid pointer to PrintDlgEx"));
-      else if (hResult == E_HANDLE)
-       g_set_error_literal (&priv->error,
-                             GTK_PRINT_ERROR,
-                             GTK_PRINT_ERROR_INTERNAL_ERROR,
-                             _("Invalid handle to PrintDlgEx"));
-      else /* E_FAIL */
-       g_set_error_literal (&priv->error,
-                             GTK_PRINT_ERROR,
-                             GTK_PRINT_ERROR_GENERAL,
-                             _("Unspecified error"));
-      goto out;
-    }
-
-  if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
-      printdlgex->dwResultAction == PD_RESULT_APPLY)
-    {
-      result = GTK_PRINT_OPERATION_RESULT_APPLY;
-      dialog_to_print_settings (op, printdlgex);
-    }
-  else
-    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  
-  if (printdlgex->dwResultAction == PD_RESULT_PRINT)
-    {
-      DOCINFOW docinfo;
-      int job_id;
-      double dpi_x, dpi_y;
-      cairo_t *cr;
-      GtkPageSetup *page_setup;
-
-      priv->print_context = _gtk_print_context_new (op);
-      page_setup = create_page_setup (op);
-      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
-      g_object_unref (page_setup);
-      
-      *do_print = TRUE;
-
-      op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
-
-      dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
-      dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
-
-      cr = cairo_create (op_win32->surface);
-      gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
-      cairo_destroy (cr);
-
-      set_hard_margins (op);
-
-      memset ( &docinfo, 0, sizeof (DOCINFOW));
-      docinfo.cbSize = sizeof (DOCINFOW); 
-      docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
-      docinfo.lpszOutput = (LPCWSTR) NULL; 
-      docinfo.lpszDatatype = (LPCWSTR) NULL; 
-      docinfo.fwType = 0; 
-
-      job_id = StartDocW (printdlgex->hDC, &docinfo); 
-      g_free ((void *)docinfo.lpszDocName);
-      if (job_id <= 0) 
-       {
-         result = GTK_PRINT_OPERATION_RESULT_ERROR;
-         g_set_error_literal (&priv->error,
-                               GTK_PRINT_ERROR,
-                               GTK_PRINT_ERROR_GENERAL,
-                               _("Error from StartDoc"));
-         *do_print = FALSE;
-         cairo_surface_destroy (op_win32->surface);
-         op_win32->surface = NULL;
-         goto out; 
-       } 
-      
-      op_win32->hdc = printdlgex->hDC;
-      op_win32->devmode = printdlgex->hDevMode;
-      op_win32->devnames = printdlgex->hDevNames;
-      op_win32->job_id = job_id;
-      
-      op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
-      op->priv->num_page_ranges = 0;
-      if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
-       op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
-                                                                   &op->priv->num_page_ranges);
-      op->priv->manual_num_copies = printdlgex->nCopies;
-      op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
-      op->priv->manual_reverse = FALSE;
-      op->priv->manual_orientation = FALSE;
-      op->priv->manual_scale = 1.0;
-      op->priv->manual_page_set = GTK_PAGE_SET_ALL;
-      op->priv->manual_number_up = 1;
-      op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-    }
-
-  op->priv->start_page = win32_start_page;
-  op->priv->end_page = win32_end_page;
-  op->priv->end_run = win32_end_run;
-  
-  out:
-  if (!*do_print && printdlgex && printdlgex->hDC != NULL)
-    DeleteDC (printdlgex->hDC);
-
-  if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) 
-    GlobalFree (printdlgex->hDevMode); 
-
-  if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) 
-    GlobalFree (printdlgex->hDevNames); 
-
-  if (page_ranges)
-    GlobalFree (page_ranges);
-
-  if (printdlgex)
-    GlobalFree (printdlgex);
-
-  if (invisible)
-    gtk_window_destroy (GTK_WINDOW (invisible));
-
-  return result;
-}
-
-GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
-                                                 gboolean           show_dialog,
-                                                 GtkWindow         *parent,
-                                                 gboolean          *do_print)
-{
-  if (show_dialog)
-    return gtk_print_operation_run_with_dialog (op, parent, do_print);
-  else
-    return gtk_print_operation_run_without_dialog (op, do_print);
-}
-
-void
-_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
-                                                     cairo_surface_t   *surface,
-                                                     GtkWindow         *parent,
-                                                     const char        *filename)
-{
-  HDC dc;
-  HENHMETAFILE metafile;
-  
-  dc = cairo_win32_surface_get_dc (surface);
-  cairo_surface_destroy (surface);
-  metafile = CloseEnhMetaFile (dc);
-  DeleteEnhMetaFile (metafile);
-  
-  ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
-                                                         cairo_surface_t *surface,
-                                                         cairo_t *cr)
-{
-  HDC dc = cairo_win32_surface_get_dc (surface);
-  StartPage (dc);
-}
-
-void
-_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
-                                                       cairo_surface_t *surface,
-                                                       cairo_t *cr)
-{
-  HDC dc;
-
-  cairo_surface_show_page (surface);
-
-  /* TODO: Enhanced metafiles don't support multiple pages.
-   */
-  dc = cairo_win32_surface_get_dc (surface);
-  EndPage (dc);
-}
-
-cairo_surface_t *
-_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             double            *dpi_x,
-                                                             double            *dpi_y,
-                                                             char             **target)
-{
-  GtkPaperSize *paper_size;
-  HDC metafile_dc;
-  RECT rect;
-  char *template;
-  char *filename;
-  gunichar2 *filename_utf16;
-  int fd;
-
-  template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
-  fd = g_mkstemp (template);
-  close (fd);
-
-  filename = g_strconcat (template, ".emf", NULL);
-  g_free (template);
-  
-  filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-  g_free (filename);
-
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-
-  /* The rectangle dimensions are given in hundredths of a millimeter */
-  rect.left = 0;
-  rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
-  rect.top = 0;
-  rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
-  
-  metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
-                                   &rect, L"Gtk+\0Print Preview\0\0");
-  if (metafile_dc == NULL)
-    {
-      g_warning ("Can't create metafile");
-      return NULL;
-    }
-
-  *target = (char *)filename_utf16;
-  
-  *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
-  *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
-
-  return cairo_win32_printing_surface_create (metafile_dc);
-}
-
-void
-_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
-                                                             GtkPageSetup      *page_setup,
-                                                             cairo_surface_t   *surface)
-{
-  /* TODO: Implement */
-}
-
-/**
- * gtk_print_run_page_setup_dialog:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- *
- * Runs a page setup dialog, letting the user modify the values from
- * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
- * is identical to the passed in @page_setup, otherwise it contains the
- * modifications done in the dialog.
- *
- * Note that this function may use a recursive mainloop to show the page
- * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
- * a problem.
- *
- * Returns: (transfer full): a new `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_print_run_page_setup_dialog (GtkWindow        *parent,
-                                GtkPageSetup     *page_setup,
-                                GtkPrintSettings *settings)
-{
-  LPPAGESETUPDLGW pagesetupdlg = NULL;
-  BOOL res;
-  gboolean free_settings;
-  const char *printer;
-  GtkPaperSize *paper_size;
-  DWORD measure_system;
-  GtkUnit unit;
-  double scale;
-
-  pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
-  if (!pagesetupdlg)
-    return NULL;
-
-  free_settings = FALSE;
-  if (settings == NULL)
-    {
-      settings = gtk_print_settings_new ();
-      free_settings = TRUE;
-    }
-  
-  memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
-
-  pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
-
-  if (parent != NULL)
-    pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
-  else
-    pagesetupdlg->hwndOwner = NULL;
-
-  pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
-  pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup, NULL);
-  pagesetupdlg->hDevNames = NULL;
-  printer = gtk_print_settings_get_printer (settings);
-  if (printer)
-    pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
-
-  GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
-                 (LPWSTR)&measure_system, sizeof (DWORD));
-
-  if (measure_system == 0)
-    {
-      pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
-      unit = GTK_UNIT_MM;
-      scale = 100;
-    }
-  else
-    {
-      pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
-      unit = GTK_UNIT_INCH;
-      scale = 1000;
-    }
-
-  /* This is the object we return, we allocate it here so that
-   * we can use the default page margins */
-  if (page_setup)
-    page_setup = gtk_page_setup_copy (page_setup);
-  else
-    page_setup = gtk_page_setup_new ();
-  
-  pagesetupdlg->Flags |= PSD_MARGINS;
-  pagesetupdlg->rtMargin.left =
-    floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
-  pagesetupdlg->rtMargin.right =
-    floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
-  pagesetupdlg->rtMargin.top = 
-    floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
-  pagesetupdlg->rtMargin.bottom =
-    floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
-
-  pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
-  pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
-  got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
-  
-  res = PageSetupDlgW (pagesetupdlg);
-  gdk_win32_set_modal_dialog_libgtk_only (NULL);
-
-  if (res)
-    {  
-      if (pagesetupdlg->hDevNames != NULL)
-       devnames_to_settings (settings, pagesetupdlg->hDevNames);
-
-      if (pagesetupdlg->hDevMode != NULL)
-       devmode_to_settings (settings, pagesetupdlg->hDevMode);
-    }
-  
-  if (res)
-    {
-      gtk_page_setup_set_orientation (page_setup, 
-                                     gtk_print_settings_get_orientation (settings));
-      paper_size = gtk_print_settings_get_paper_size (settings);
-      if (paper_size)
-       {
-         gtk_page_setup_set_paper_size (page_setup, paper_size);
-         gtk_paper_size_free (paper_size);
-       }
-
-      if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
-       {
-         unit = GTK_UNIT_MM;
-         scale = 100;
-       }
-      else
-       {
-         unit = GTK_UNIT_INCH;
-         scale = 1000;
-       }
-
-      gtk_page_setup_set_left_margin (page_setup,
-                                     pagesetupdlg->rtMargin.left / scale,
-                                     unit);
-      gtk_page_setup_set_right_margin (page_setup,
-                                      pagesetupdlg->rtMargin.right / scale,
-                                      unit);
-      gtk_page_setup_set_top_margin (page_setup,
-                                    pagesetupdlg->rtMargin.top / scale,
-                                    unit);
-      gtk_page_setup_set_bottom_margin (page_setup,
-                                       pagesetupdlg->rtMargin.bottom / scale,
-                                       unit);
-    }
-  
-  if (free_settings)
-    g_object_unref (settings);
-
-  return page_setup;
-}
-
-/**
- * gtk_print_run_page_setup_dialog_async:
- * @parent: (nullable): transient parent
- * @page_setup: (nullable): an existing `GtkPageSetup`
- * @settings: a `GtkPrintSettings`
- * @done_cb: (scope async): a function to call when the user saves
- *    the modified page setup
- * @data: user data to pass to @done_cb
- *
- * Runs a page setup dialog, letting the user modify the values from @page_setup.
- *
- * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after
- * showing the page setup dialog on platforms that support this, and calls @done_cb
- * from a signal handler for the ::response signal of the dialog.
- */
-void
-gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
-                                      GtkPageSetup         *page_setup,
-                                      GtkPrintSettings     *settings,
-                                      GtkPageSetupDoneFunc  done_cb,
-                                      gpointer              data)
-{
-  GtkPageSetup *new_page_setup;
-
-  new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
-  done_cb (new_page_setup, data);
-  g_object_unref (new_page_setup);
-}
diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c
deleted file mode 100644 (file)
index 1835002..0000000
+++ /dev/null
@@ -1,3564 +0,0 @@
-/* GtkPrintUnixDialog
- * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
- * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
- * Copyright © 2006, 2007 Christian Persch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <math.h>
-
-#include "gtkprintunixdialog.h"
-
-#include "gtkcustompaperunixdialog.h"
-#include "gtkprintbackendprivate.h"
-#include "gtkprinterprivate.h"
-#include "gtkprinteroptionwidgetprivate.h"
-#include "gtkprintutilsprivate.h"
-
-#include "gtkspinbutton.h"
-#include "gtkimage.h"
-#include "gtknotebook.h"
-#include "gtkscrolledwindow.h"
-#include "gtktogglebutton.h"
-#include "gtkdrawingarea.h"
-#include "gtkbox.h"
-#include "gtkgrid.h"
-#include "gtkframe.h"
-#include "gtklabel.h"
-#include "gtkbuildable.h"
-#include "deprecated/gtkmessagedialog.h"
-#include "gtkbutton.h"
-#include "gtksnapshot.h"
-#include "gtkrenderbackgroundprivate.h"
-#include "gtkrenderborderprivate.h"
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-#include "gtktypebuiltins.h"
-#include "deprecated/gtkdialogprivate.h"
-#include "gtkwidgetprivate.h"
-#include "gtkcsscolorvalueprivate.h"
-
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-
-/**
- * GtkPrintUnixDialog:
- *
- * `GtkPrintUnixDialog` implements a print dialog for platforms
- * which don’t provide a native print dialog, like Unix.
- *
- * ![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
- * <object class="GtkPrintUnixDialog" id="dialog1">
- *   <child internal-child="notebook">
- *     <object class="GtkNotebook" id="notebook">
- *       <child>
- *         <object type="GtkNotebookPage">
- *           <property name="tab_expand">False</property>
- *           <property name="tab_fill">False</property>
- *           <property name="tab">
- *             <object class="GtkLabel" id="tablabel">
- *               <property name="label">Tab label</property>
- *             </object>
- *           </property>
- *           <property name="child">
- *             <object class="GtkLabel" id="tabcontent">
- *               <property name="label">Content on notebook tab</property>
- *             </object>
- *           </property>
- *         </object>
- *       </child>
- *     </object>
- *   </child>
- * </object>
- * ```
- *
- * # CSS nodes
- *
- * `GtkPrintUnixDialog` has a single CSS node with name window. The style classes
- * dialog and print are added.
- */
-
-
-#define EXAMPLE_PAGE_AREA_SIZE 110
-#define RULER_DISTANCE 7.5
-#define RULER_RADIUS 2
-
-
-static void     gtk_print_unix_dialog_constructed  (GObject            *object);
-static void     gtk_print_unix_dialog_dispose      (GObject            *object);
-static void     gtk_print_unix_dialog_finalize     (GObject            *object);
-static void     gtk_print_unix_dialog_set_property (GObject            *object,
-                                                    guint               prop_id,
-                                                    const GValue       *value,
-                                                    GParamSpec         *pspec);
-static void     gtk_print_unix_dialog_get_property (GObject            *object,
-                                                    guint               prop_id,
-                                                    GValue             *value,
-                                                    GParamSpec         *pspec);
-static void     unschedule_idle_mark_conflicts     (GtkPrintUnixDialog *dialog);
-static void     selected_printer_changed           (GtkPrintUnixDialog *dialog);
-static void     clear_per_printer_ui               (GtkPrintUnixDialog *dialog);
-static void     printer_added_cb                   (GListModel         *model,
-                                                    guint               position,
-                                                    guint               removed,
-                                                    guint               added,
-                                                    GtkPrintUnixDialog *dialog);
-static void     printer_status_cb                  (GtkPrintBackend    *backend,
-                                                    GtkPrinter         *printer,
-                                                    GtkPrintUnixDialog *dialog);
-static void     update_collate_icon                (GtkToggleButton    *toggle_button,
-                                                    GtkPrintUnixDialog *dialog);
-static void     error_dialogs                      (GtkPrintUnixDialog *print_dialog,
-                                                   int                 print_dialog_response_id,
-                                                   gpointer            data);
-static gboolean page_range_entry_focus_changed     (GtkWidget          *entry,
-                                                    GParamSpec         *pspec,
-                                                    GtkPrintUnixDialog *dialog);
-static void     update_page_range_entry_sensitivity(GtkWidget          *button,
-                                                   GtkPrintUnixDialog *dialog);
-static void     update_print_at_entry_sensitivity  (GtkWidget          *button,
-                                                   GtkPrintUnixDialog *dialog);
-static void     update_print_at_option             (GtkPrintUnixDialog *dialog);
-static void     update_dialog_from_capabilities    (GtkPrintUnixDialog *dialog);
-static void     draw_collate                       (GtkDrawingArea     *da,
-                                                   cairo_t            *cr,
-                                                    int                 width,
-                                                    int                 height,
-                                                    gpointer            data);
-static gboolean is_printer_active                  (gpointer            item,
-                                                    gpointer            data);
-static  int     default_printer_list_sort_func     (gconstpointer        a,
-                                                    gconstpointer        b,
-                                                   gpointer             user_data);
-static void     update_number_up_layout            (GtkPrintUnixDialog  *dialog);
-static void     draw_page                          (GtkDrawingArea      *da,
-                                                   cairo_t             *cr,
-                                                    int                  width,
-                                                    int                  height,
-                                                    gpointer             data);
-
-
-static gboolean dialog_get_collate                 (GtkPrintUnixDialog *dialog);
-static gboolean dialog_get_reverse                 (GtkPrintUnixDialog *dialog);
-static int      dialog_get_n_copies                (GtkPrintUnixDialog *dialog);
-
-static gboolean set_active_printer                 (GtkPrintUnixDialog *dialog,
-                                                    const char         *printer_name);
-static void redraw_page_layout_preview             (GtkPrintUnixDialog *dialog);
-static GListModel *load_print_backends             (GtkPrintUnixDialog *dialog);
-
-/* GtkBuildable */
-static void gtk_print_unix_dialog_buildable_init                    (GtkBuildableIface *iface);
-static GObject *gtk_print_unix_dialog_buildable_get_internal_child  (GtkBuildable *buildable,
-                                                                     GtkBuilder   *builder,
-                                                                     const char   *childname);
-
-static const char common_paper_sizes[][16] = {
-  "na_letter",
-  "na_legal",
-  "iso_a4",
-  "iso_a5",
-  "roc_16k",
-  "iso_b5",
-  "jis_b5",
-  "na_number-10",
-  "iso_dl",
-  "jpn_chou3",
-  "na_ledger",
-  "iso_a3",
-};
-
-/* Keep in line with liststore defined in gtkprintunixdialog.ui */
-enum {
-  PAGE_SETUP_LIST_COL_PAGE_SETUP,
-  PAGE_SETUP_LIST_COL_IS_SEPARATOR,
-  PAGE_SETUP_LIST_N_COLS
-};
-
-/* Keep in line with liststore defined in gtkprintunixdialog.ui */
-enum {
-  PRINTER_LIST_COL_ICON,
-  PRINTER_LIST_COL_NAME,
-  PRINTER_LIST_COL_STATE,
-  PRINTER_LIST_COL_JOBS,
-  PRINTER_LIST_COL_LOCATION,
-  PRINTER_LIST_COL_PRINTER_OBJ,
-  PRINTER_LIST_N_COLS
-};
-
-enum {
-  PROP_0,
-  PROP_PAGE_SETUP,
-  PROP_CURRENT_PAGE,
-  PROP_PRINT_SETTINGS,
-  PROP_SELECTED_PRINTER,
-  PROP_MANUAL_CAPABILITIES,
-  PROP_SUPPORT_SELECTION,
-  PROP_HAS_SELECTION,
-  PROP_EMBED_PAGE_SETUP
-};
-
-typedef struct _GtkPrintUnixDialogClass    GtkPrintUnixDialogClass;
-
-struct _GtkPrintUnixDialog
-{
-  GtkDialog parent_instance;
-
-  GtkWidget *notebook;
-
-  GtkWidget *printer_list;
-
-  GtkPrintCapabilities manual_capabilities;
-  GtkPrintCapabilities printer_capabilities;
-
-  GtkPageSetup *page_setup;
-  gboolean page_setup_set;
-  gboolean embed_page_setup;
-  GListStore *page_setup_list;
-  GListStore *custom_paper_list;
-  GListStore *manage_papers_list;
-
-  gboolean support_selection;
-  gboolean has_selection;
-
-  GtkWidget *all_pages_radio;
-  GtkWidget *current_page_radio;
-  GtkWidget *selection_radio;
-  GtkWidget *range_table;
-  GtkWidget *page_range_radio;
-  GtkWidget *page_range_entry;
-
-  GtkWidget *copies_spin;
-  GtkWidget *collate_check;
-  GtkWidget *reverse_check;
-  GtkWidget *collate_image;
-  GtkWidget *page_layout_preview;
-  GtkWidget *scale_spin;
-  GtkWidget *page_set_combo;
-  GtkWidget *print_now_radio;
-  GtkWidget *print_at_radio;
-  GtkWidget *print_at_entry;
-  GtkWidget *print_hold_radio;
-  GtkWidget *paper_size_combo;
-  GtkWidget *orientation_combo;
-  gboolean internal_page_setup_change;
-  gboolean updating_print_at;
-  GtkPrinterOptionWidget *pages_per_sheet;
-  GtkPrinterOptionWidget *duplex;
-  GtkPrinterOptionWidget *paper_type;
-  GtkPrinterOptionWidget *paper_source;
-  GtkPrinterOptionWidget *output_tray;
-  GtkPrinterOptionWidget *job_prio;
-  GtkPrinterOptionWidget *billing_info;
-  GtkPrinterOptionWidget *cover_before;
-  GtkPrinterOptionWidget *cover_after;
-  GtkPrinterOptionWidget *number_up_layout;
-
-  GtkWidget *conflicts_widget;
-
-  GtkWidget *job_page;
-  GtkWidget *finishing_table;
-  GtkWidget *finishing_page;
-  GtkWidget *image_quality_table;
-  GtkWidget *image_quality_page;
-  GtkWidget *color_table;
-  GtkWidget *color_page;
-
-  GtkWidget *advanced_vbox;
-  GtkWidget *advanced_page;
-
-  GtkWidget *extension_point;
-
-  /* These are set initially on selected printer (either default printer,
-   * printer taken from set settings, or user-selected), but when any
-   * setting is changed by the user it is cleared.
-   */
-  GtkPrintSettings *initial_settings;
-
-  GtkPrinterOption *number_up_layout_n_option;
-  GtkPrinterOption *number_up_layout_2_option;
-
-  /* This is the initial printer set by set_settings. We look for it in
-   * the added printers. We clear this whenever the user manually changes
-   * to another printer, when the user changes a setting or when we find
-   * this printer.
-   */
-  char *waiting_for_printer;
-  gboolean internal_printer_change;
-
-  GList *print_backends;
-
-  GtkPrinter *current_printer;
-  GtkPrinter *request_details_printer;
-  gulong request_details_tag;
-  GtkPrinterOptionSet *options;
-  gulong options_changed_handler;
-  gulong mark_conflicts_id;
-
-  char *format_for_printer;
-
-  int current_page;
-  GtkCssNode *collate_paper_node;
-  GtkCssNode *page_layout_paper_node;
-};
-
-struct _GtkPrintUnixDialogClass
-{
-  GtkDialogClass parent_class;
-};
-
-G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
-                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-                                                gtk_print_unix_dialog_buildable_init))
-
-static GtkBuildableIface *parent_buildable_iface;
-
-static gboolean
-is_default_printer (GtkPrintUnixDialog *dialog,
-                    GtkPrinter         *printer)
-{
-  if (dialog->format_for_printer)
-    return strcmp (dialog->format_for_printer,
-                   gtk_printer_get_name (printer)) == 0;
- else
-   return gtk_printer_is_default (printer);
-}
-
-static void
-gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
-{
-  GObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-
-  object_class = (GObjectClass *) class;
-  widget_class = (GtkWidgetClass *) class;
-
-  object_class->constructed = gtk_print_unix_dialog_constructed;
-  object_class->finalize = gtk_print_unix_dialog_finalize;
-  object_class->dispose = gtk_print_unix_dialog_dispose;
-  object_class->set_property = gtk_print_unix_dialog_set_property;
-  object_class->get_property = gtk_print_unix_dialog_get_property;
-
-  /**
-   * GtkPrintUnixDialog:page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_page_setup)
-   *
-   * The `GtkPageSetup` object to use.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_PAGE_SETUP,
-                                   g_param_spec_object ("page-setup", NULL, NULL,
-                                                        GTK_TYPE_PAGE_SETUP,
-                                                        GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintUnixDialog:current-page: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_current_page org.gtk.Property.set=gtk_print_unix_dialog_set_current_page)
-   *
-   * The current page in the document.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_CURRENT_PAGE,
-                                   g_param_spec_int ("current-page", NULL, NULL,
-                                                     -1,
-                                                     G_MAXINT,
-                                                     -1,
-                                                     GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintUnixDialog:print-settings: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_settings org.gtk.Property.set=gtk_print_unix_dialog_set_settings)
-   *
-   * The `GtkPrintSettings` object used for this dialog.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_PRINT_SETTINGS,
-                                   g_param_spec_object ("print-settings", NULL, NULL,
-                                                        GTK_TYPE_PRINT_SETTINGS,
-                                                        GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintUnixDialog:selected-printer: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_selected_printer)
-   *
-   * The `GtkPrinter` which is selected.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_SELECTED_PRINTER,
-                                   g_param_spec_object ("selected-printer", NULL, NULL,
-                                                        GTK_TYPE_PRINTER,
-                                                        GTK_PARAM_READABLE));
-
-  /**
-   * GtkPrintUnixDialog:manual-capabilities: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_manual_capabilities org.gtk.Property.set=gtk_print_unix_dialog_set_manual_capabilities)
-   *
-   * Capabilities the application can handle.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_MANUAL_CAPABILITIES,
-                                   g_param_spec_flags ("manual-capabilities", NULL, NULL,
-                                                       GTK_TYPE_PRINT_CAPABILITIES,
-                                                       0,
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintUnixDialog:support-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_support_selection org.gtk.Property.set=gtk_print_unix_dialog_set_support_selection)
-   *
-   * Whether the dialog supports selection.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_SUPPORT_SELECTION,
-                                   g_param_spec_boolean ("support-selection", NULL, NULL,
-                                                         FALSE,
-                                                         GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintUnixDialog:has-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_has_selection org.gtk.Property.set=gtk_print_unix_dialog_set_has_selection)
-   *
-   * Whether the application has a selection.
-   */
-  g_object_class_install_property (object_class,
-                                   PROP_HAS_SELECTION,
-                                   g_param_spec_boolean ("has-selection", NULL, NULL,
-                                                         FALSE,
-                                                         GTK_PARAM_READWRITE));
-
-   /**
-    * GtkPrintUnixDialog:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_embed_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_embed_page_setup)
-    *
-    * %TRUE if the page setup controls are embedded.
-    */
-   g_object_class_install_property (object_class,
-                                   PROP_EMBED_PAGE_SETUP,
-                                   g_param_spec_boolean ("embed-page-setup", NULL, NULL,
-                                                         FALSE,
-                                                         GTK_PARAM_READWRITE));
-
-  /* Bind class to template
-   */
-  gtk_widget_class_set_template_from_resource (widget_class,
-                                              "/org/gtk/libgtk/ui/gtkprintunixdialog.ui");
-
-  /* GtkTreeView / GtkTreeModel */
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, printer_list);
-
-  /* General Widgetry */
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, notebook);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, current_page_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, selection_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, range_table);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_entry);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, copies_spin);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_check);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, reverse_check);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_image);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_layout_preview);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, scale_spin);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_set_combo);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_now_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_entry);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_hold_radio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_size_combo);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, orientation_combo);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, conflicts_widget);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_page);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_table);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_page);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_table);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_page);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_table);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_page);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_vbox);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_page);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, extension_point);
-
-  /* GtkPrinterOptionWidgets... */
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, pages_per_sheet);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, duplex);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_type);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_source);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, output_tray);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_prio);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, billing_info);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_before);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_after);
-  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, number_up_layout);
-
-  /* Callbacks handled in the UI */
-  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
-  gtk_widget_class_bind_template_callback (widget_class, error_dialogs);
-  gtk_widget_class_bind_template_callback (widget_class, page_range_entry_focus_changed);
-  gtk_widget_class_bind_template_callback (widget_class, update_page_range_entry_sensitivity);
-  gtk_widget_class_bind_template_callback (widget_class, update_print_at_entry_sensitivity);
-  gtk_widget_class_bind_template_callback (widget_class, update_print_at_option);
-  gtk_widget_class_bind_template_callback (widget_class, update_dialog_from_capabilities);
-  gtk_widget_class_bind_template_callback (widget_class, update_collate_icon);
-  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
-  gtk_widget_class_bind_template_callback (widget_class, update_number_up_layout);
-  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
-}
-
-/* Returns a toplevel GtkWindow, or NULL if none */
-static GtkWindow *
-get_toplevel (GtkWidget *widget)
-{
-  GtkWidget *toplevel = NULL;
-
-  toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
-  if (GTK_IS_WINDOW (toplevel))
-    return GTK_WINDOW (toplevel);
-  else
-    return NULL;
-}
-
-static void
-set_busy_cursor (GtkPrintUnixDialog *dialog,
-                 gboolean            busy)
-{
-  GtkWidget *widget;
-  GtkWindow *toplevel;
-
-  toplevel = get_toplevel (GTK_WIDGET (dialog));
-  widget = GTK_WIDGET (toplevel);
-
-  if (!toplevel || !gtk_widget_get_realized (widget))
-    return;
-
-  if (busy)
-    gtk_widget_set_cursor_from_name (widget, "progress");
-  else
-    gtk_widget_set_cursor (widget, NULL);
-}
-
-typedef struct {
-  GMainLoop *loop;
-  int response;
-} ConfirmationData;
-
-static void
-on_confirmation_dialog_response (GtkWidget *dialog,
-                                 int        response,
-                                 gpointer   user_data)
-{
-  ConfirmationData *data = user_data;
-
-  data->response = response;
-
-  g_main_loop_quit (data->loop);
-
-  gtk_window_destroy (GTK_WINDOW (dialog));
-}
-
-/* This function handles error messages before printing.
- */
-static void
-error_dialogs (GtkPrintUnixDialog *dialog,
-               int                 dialog_response_id,
-               gpointer            data)
-{
-  if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK)
-    {
-      GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog);
-
-      if (printer != NULL)
-        {
-          if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer))
-            {
-              g_signal_stop_emission_by_name (dialog, "response");
-              return;
-            }
-
-          /* Shows overwrite confirmation dialog in the case of printing
-           * to file which already exists.
-           */
-          if (gtk_printer_is_virtual (printer))
-            {
-              GtkPrinterOption *option =
-                gtk_printer_option_set_lookup (dialog->options,
-                                               "gtk-main-page-custom-input");
-
-              if (option != NULL &&
-                  option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
-                {
-                  GFile *file = g_file_new_for_uri (option->value);
-
-                  if (g_file_query_exists (file, NULL))
-                    {
-                      GtkWidget *message_dialog;
-                      GtkWindow *toplevel;
-                      char *basename;
-                      char *dirname;
-                      GFile *parent;
-
-                      toplevel = get_toplevel (GTK_WIDGET (dialog));
-
-                      basename = g_file_get_basename (file);
-                      parent = g_file_get_parent (file);
-                      dirname = g_file_get_parse_name (parent);
-                      g_object_unref (parent);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-                      message_dialog = gtk_message_dialog_new (toplevel,
-                                                               GTK_DIALOG_MODAL |
-                                                               GTK_DIALOG_DESTROY_WITH_PARENT,
-                                                               GTK_MESSAGE_QUESTION,
-                                                               GTK_BUTTONS_NONE,
-                                                               _("A file named “%s” already exists.  Do you want to replace it?"),
-                                                               basename);
-
-                      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
-                                                                _("The file already exists in “%s”.  Replacing it will "
-                                                                "overwrite its contents."),
-                                                                dirname);
-
-                      gtk_dialog_add_button (GTK_DIALOG (message_dialog),
-                                             _("_Cancel"),
-                                             GTK_RESPONSE_CANCEL);
-                      gtk_dialog_add_button (GTK_DIALOG (message_dialog),
-                                             _("_Replace"),
-                                             GTK_RESPONSE_ACCEPT);
-                      gtk_dialog_set_default_response (GTK_DIALOG (message_dialog),
-                                                       GTK_RESPONSE_ACCEPT);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-                      if (gtk_window_has_group (toplevel))
-                        gtk_window_group_add_window (gtk_window_get_group (toplevel),
-                                                     GTK_WINDOW (message_dialog));
-
-                      gtk_window_present (GTK_WINDOW (message_dialog));
-
-                      /* Block on the confirmation dialog until we have a response,
-                       * so that we can stop the "response" signal emission on the
-                       * print dialog
-                       */
-                      ConfirmationData cdata;
-
-                      cdata.loop = g_main_loop_new (NULL, FALSE);
-                      cdata.response = 0;
-
-                      g_signal_connect (message_dialog, "response",
-                                        G_CALLBACK (on_confirmation_dialog_response),
-                                        &cdata);
-
-                      g_main_loop_run (cdata.loop);
-                      g_main_loop_unref (cdata.loop);
-
-                      g_free (dirname);
-                      g_free (basename);
-
-                      if (cdata.response != GTK_RESPONSE_ACCEPT)
-                        g_signal_stop_emission_by_name (dialog, "response");
-                    }
-
-                  g_object_unref (file);
-                }
-            }
-        }
-    }
-}
-
-static char *
-get_printer_key (GtkPrinter *printer)
-{
-  return g_strconcat ("", gtk_printer_get_name (printer), " ", gtk_printer_get_location (printer), NULL);
-}
-
-static void
-setup_paper_size_item (GtkSignalListItemFactory *factory,
-                       GtkListItem              *item)
-{
-  GtkWidget *label;
-
-  label = gtk_label_new ("");
-  gtk_widget_set_halign (label, GTK_ALIGN_START);
-  gtk_list_item_set_child (item, label);
-}
-
-static void
-bind_paper_size_list_item (GtkSignalListItemFactory *factory,
-                           GtkListItem              *item,
-                           GtkPrintUnixDialog       *self)
-{
-  GtkPageSetup *page_setup;
-  GtkWidget *label;
-  guint pos;
-  GListModel *papers;
-  GListModel *model;
-  gpointer first;
-
-  page_setup = gtk_list_item_get_item (item);
-  label = gtk_list_item_get_child (item);
-
-  pos = gtk_list_item_get_position (item);
-  papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
-  model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
-  if (model != G_LIST_MODEL (self->manage_papers_list))
-    {
-      GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
-      gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
-    }
-  else
-    gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
-
-  first = g_list_model_get_item (model, 0);
-  g_object_unref (first);
-  if (pos != 0 &&
-      page_setup == GTK_PAGE_SETUP (first))
-    gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
-  else
-    gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
-}
-
-static void
-bind_paper_size_item (GtkSignalListItemFactory *factory,
-                      GtkListItem              *item,
-                      GtkPrintUnixDialog       *self)
-{
-  GtkWidget *label;
-
-  bind_paper_size_list_item (factory, item, self);
-
-  label = gtk_list_item_get_child (item);
-  gtk_widget_remove_css_class (label, "separator-before");
-}
-
-static void
-gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
-{
-  GtkWidget *widget;
-  GListModel *model;
-  GListModel *sorted;
-  GListModel *filtered;
-  GListModel *selection;
-  GtkSorter *sorter;
-  GtkFilter *filter;
-  GtkStringFilter *filter1;
-  GtkCustomFilter *filter2;
-  GtkListItemFactory *factory;
-  GListStore *store;
-  GListModel *paper_size_list;
-  GtkPageSetup *page_setup;
-
-  dialog->print_backends = NULL;
-  dialog->current_page = -1;
-  dialog->number_up_layout_n_option = NULL;
-  dialog->number_up_layout_2_option = NULL;
-
-  dialog->page_setup = gtk_page_setup_new ();
-  dialog->page_setup_set = FALSE;
-  dialog->embed_page_setup = FALSE;
-  dialog->internal_page_setup_change = FALSE;
-  dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
-  page_setup = gtk_page_setup_new ();
-  g_list_store_append (dialog->manage_papers_list, page_setup);
-  g_object_unref (page_setup);
-
-  dialog->support_selection = FALSE;
-  dialog->has_selection = FALSE;
-
-  g_type_ensure (GTK_TYPE_PRINTER);
-  g_type_ensure (GTK_TYPE_PRINTER_OPTION);
-  g_type_ensure (GTK_TYPE_PRINTER_OPTION_SET);
-  g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
-
-  gtk_widget_init_template (GTK_WIDGET (dialog));
-  gtk_widget_add_css_class (GTK_WIDGET (dialog), "print");
-
-  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
-  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                          _("Pre_view"), GTK_RESPONSE_APPLY,
-                          _("_Cancel"), GTK_RESPONSE_CANCEL,
-                          _("_Print"), GTK_RESPONSE_OK,
-                          NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  widget = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  gtk_widget_set_sensitive (widget, FALSE);
-
-  gtk_widget_set_visible (dialog->selection_radio, FALSE);
-  gtk_widget_set_visible (dialog->conflicts_widget, FALSE);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
-  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
-  g_object_unref (factory);
-
-  factory = gtk_signal_list_item_factory_new ();
-  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
-  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
-  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
-  g_object_unref (factory);
-
-  store = g_list_store_new (G_TYPE_LIST_MODEL);
-  g_list_store_append (store, dialog->page_setup_list);
-  g_list_store_append (store, dialog->custom_paper_list);
-  g_list_store_append (store, dialog->manage_papers_list);
-  paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
-  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
-  g_object_unref (paper_size_list);
-
-  /* Load backends */
-  model = load_print_backends (dialog);
-  sorter = GTK_SORTER (gtk_custom_sorter_new (default_printer_list_sort_func, NULL, NULL));
-  sorted = G_LIST_MODEL (gtk_sort_list_model_new (model, sorter));
-
-  filter = GTK_FILTER (gtk_every_filter_new ());
-
-  filter1 = gtk_string_filter_new (
-                gtk_cclosure_expression_new (G_TYPE_STRING,
-                                             NULL, 0, NULL,
-                                             G_CALLBACK (get_printer_key),
-                                             NULL, NULL));
-  gtk_string_filter_set_match_mode (filter1, GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
-  gtk_string_filter_set_ignore_case (filter1, TRUE);
-  gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter1));
-
-  filter2 = gtk_custom_filter_new (is_printer_active, dialog, NULL);
-  gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter2));
-
-  filtered = G_LIST_MODEL (gtk_filter_list_model_new (sorted, filter));
-
-  selection = G_LIST_MODEL (gtk_single_selection_new (filtered));
-  gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), FALSE);
-  gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (selection), GTK_INVALID_LIST_POSITION);
-  gtk_column_view_set_model (GTK_COLUMN_VIEW (dialog->printer_list), GTK_SELECTION_MODEL (selection));
-  g_signal_connect (selection, "items-changed", G_CALLBACK (printer_added_cb), dialog);
-  g_signal_connect_swapped (selection, "notify::selected", G_CALLBACK (selected_printer_changed), dialog);
-  g_object_unref (selection);
-
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-
-  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->collate_image),
-                                  draw_collate,
-                                  dialog, NULL);
-  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->page_layout_preview),
-                                  draw_page,
-                                  dialog, NULL);
-
-  gtk_css_node_set_name (gtk_widget_get_css_node (dialog->collate_image), g_quark_from_static_string ("drawing"));
-  gtk_css_node_set_name (gtk_widget_get_css_node (dialog->page_layout_preview), g_quark_from_static_string ("drawing"));
-
-  dialog->collate_paper_node = gtk_css_node_new();
-  gtk_css_node_set_name (dialog->collate_paper_node, g_quark_from_static_string ("paper"));
-  gtk_css_node_set_parent (dialog->collate_paper_node,
-                           gtk_widget_get_css_node (dialog->collate_image));
-  g_object_unref (dialog->collate_paper_node);
-
-  dialog->page_layout_paper_node = gtk_css_node_new();
-  gtk_css_node_set_name (dialog->page_layout_paper_node, g_quark_from_static_string ("paper"));
-  gtk_css_node_set_parent (dialog->page_layout_paper_node,
-                           gtk_widget_get_css_node (dialog->page_layout_preview));
-  g_object_unref (dialog->page_layout_paper_node);
-}
-
-static void
-gtk_print_unix_dialog_constructed (GObject *object)
-{
-  gboolean use_header;
-
-  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->constructed (object);
-
-  g_object_get (object, "use-header-bar", &use_header, NULL);
-  if (use_header)
-    {
-       /* Reorder the preview button */
-       GtkWidget *button, *parent;
-       button = gtk_dialog_get_widget_for_response (GTK_DIALOG (object), GTK_RESPONSE_APPLY);
-       g_object_ref (button);
-       parent = gtk_widget_get_ancestor (button, GTK_TYPE_HEADER_BAR);
-       gtk_box_remove (GTK_BOX (gtk_widget_get_parent (button)), button);
-       gtk_header_bar_pack_end (GTK_HEADER_BAR (parent), button);
-       g_object_unref (button);
-    }
-
-  update_dialog_from_capabilities (GTK_PRINT_UNIX_DIALOG (object));
-}
-
-static void
-gtk_print_unix_dialog_dispose (GObject *object)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
-  /* Make sure we don't destroy custom widgets owned by the backends */
-  clear_per_printer_ui (dialog);
-
-  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->dispose (object);
-}
-
-static void
-disconnect_printer_details_request (GtkPrintUnixDialog *dialog,
-                                    gboolean            details_failed)
-{
-  if (dialog->request_details_tag)
-    {
-      g_signal_handler_disconnect (dialog->request_details_printer,
-                                   dialog->request_details_tag);
-      dialog->request_details_tag = 0;
-      set_busy_cursor (dialog, FALSE);
-      if (details_failed)
-        gtk_printer_set_state_message (dialog->request_details_printer, _("Getting printer information failed"));
-      g_clear_object (&dialog->request_details_printer);
-    }
-}
-
-static void
-gtk_print_unix_dialog_finalize (GObject *object)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-  GList *iter;
-
-  unschedule_idle_mark_conflicts (dialog);
-  disconnect_printer_details_request (dialog, FALSE);
-
-  g_clear_object (&dialog->current_printer);
-  g_clear_object (&dialog->options);
-
-  if (dialog->number_up_layout_2_option)
-    {
-      dialog->number_up_layout_2_option->choices[0] = NULL;
-      dialog->number_up_layout_2_option->choices[1] = NULL;
-      g_free (dialog->number_up_layout_2_option->choices_display[0]);
-      g_free (dialog->number_up_layout_2_option->choices_display[1]);
-      dialog->number_up_layout_2_option->choices_display[0] = NULL;
-      dialog->number_up_layout_2_option->choices_display[1] = NULL;
-      g_object_unref (dialog->number_up_layout_2_option);
-      dialog->number_up_layout_2_option = NULL;
-    }
-
-  g_clear_object (&dialog->number_up_layout_n_option);
-  g_clear_object (&dialog->page_setup);
-  g_clear_object (&dialog->initial_settings);
-  g_clear_pointer (&dialog->waiting_for_printer, (GDestroyNotify)g_free);
-  g_clear_pointer (&dialog->format_for_printer, (GDestroyNotify)g_free);
-
-  for (iter = dialog->print_backends; iter != NULL; iter = iter->next)
-    gtk_print_backend_destroy (GTK_PRINT_BACKEND (iter->data));
-  g_list_free_full (dialog->print_backends, g_object_unref);
-  dialog->print_backends = NULL;
-
-  g_clear_object (&dialog->page_setup_list);
-  g_clear_object (&dialog->custom_paper_list);
-  g_clear_object (&dialog->manage_papers_list);
-
-  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
-}
-
-static void
-gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
-{
-  parent_buildable_iface = g_type_interface_peek_parent (iface);
-
-  iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
-}
-
-static GObject *
-gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
-                                                    GtkBuilder   *builder,
-                                                    const char   *childname)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (buildable);
-
-  if (strcmp (childname, "notebook") == 0)
-    return G_OBJECT (dialog->notebook);
-
-  return parent_buildable_iface->get_internal_child (buildable, builder, childname);
-}
-
-static void
-printer_status_cb (GtkPrintBackend    *backend,
-                   GtkPrinter         *printer,
-                   GtkPrintUnixDialog *dialog)
-{
-  GListModel *model;
-
-  /* When the pause state change then we need to update sensitive property
-   * of GTK_RESPONSE_OK button inside of selected_printer_changed function.
-   */
-  selected_printer_changed (dialog);
-
-  model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
-
-  if (gtk_print_backend_printer_list_is_done (backend) &&
-      gtk_printer_is_default (printer) &&
-      gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
-    set_active_printer (dialog, gtk_printer_get_name (printer));
-}
-
-static void
-printer_added_cb (GListModel         *model,
-                  guint               position,
-                  guint               removed,
-                  guint               added,
-                  GtkPrintUnixDialog *dialog)
-{
-  guint i;
-
-  for (i = position; i < position + added; i++)
-    {
-      GtkPrinter *printer = g_list_model_get_item (model, i);
-
-      if (dialog->waiting_for_printer != NULL &&
-          strcmp (gtk_printer_get_name (printer), dialog->waiting_for_printer) == 0)
-        {
-          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
-          g_free (dialog->waiting_for_printer);
-          dialog->waiting_for_printer = NULL;
-          g_object_unref (printer);
-          return;
-        }
-      else if (is_default_printer (dialog, printer) &&
-               gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
-        {
-          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
-          g_object_unref (printer);
-          return;
-        }
-
-      g_object_unref (printer);
-    }
-}
-
-static GListModel *
-load_print_backends (GtkPrintUnixDialog *dialog)
-{
-  GList *node;
-  GListStore *lists;
-
-  lists = g_list_store_new (G_TYPE_LIST_MODEL);
-
-  if (g_module_supported ())
-    dialog->print_backends = gtk_print_backend_load_modules ();
-
-  for (node = dialog->print_backends; node != NULL; node = node->next)
-    {
-      GtkPrintBackend *backend = node->data;
-
-      g_signal_connect_object (backend, "printer-status-changed",
-                               G_CALLBACK (printer_status_cb), G_OBJECT (dialog), 0);
-      g_list_store_append (lists, gtk_print_backend_get_printers (backend));
-    }
-
-  return G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (lists)));
-}
-
-static void
-gtk_print_unix_dialog_set_property (GObject      *object,
-                                    guint         prop_id,
-                                    const GValue *value,
-                                    GParamSpec   *pspec)
-
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
-  switch (prop_id)
-    {
-    case PROP_PAGE_SETUP:
-      gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
-      break;
-    case PROP_CURRENT_PAGE:
-      gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
-      break;
-    case PROP_PRINT_SETTINGS:
-      gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
-      break;
-    case PROP_MANUAL_CAPABILITIES:
-      gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value));
-      break;
-    case PROP_SUPPORT_SELECTION:
-      gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value));
-      break;
-    case PROP_HAS_SELECTION:
-      gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value));
-      break;
-    case PROP_EMBED_PAGE_SETUP:
-      gtk_print_unix_dialog_set_embed_page_setup (dialog, g_value_get_boolean (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_print_unix_dialog_get_property (GObject    *object,
-                                    guint       prop_id,
-                                    GValue     *value,
-                                    GParamSpec *pspec)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
-
-  switch (prop_id)
-    {
-    case PROP_PAGE_SETUP:
-      g_value_set_object (value, dialog->page_setup);
-      break;
-    case PROP_CURRENT_PAGE:
-      g_value_set_int (value, dialog->current_page);
-      break;
-    case PROP_PRINT_SETTINGS:
-      g_value_take_object (value, gtk_print_unix_dialog_get_settings (dialog));
-      break;
-    case PROP_SELECTED_PRINTER:
-      g_value_set_object (value, dialog->current_printer);
-      break;
-    case PROP_MANUAL_CAPABILITIES:
-      g_value_set_flags (value, dialog->manual_capabilities);
-      break;
-    case PROP_SUPPORT_SELECTION:
-      g_value_set_boolean (value, dialog->support_selection);
-      break;
-    case PROP_HAS_SELECTION:
-      g_value_set_boolean (value, dialog->has_selection);
-      break;
-    case PROP_EMBED_PAGE_SETUP:
-      g_value_set_boolean (value, dialog->embed_page_setup);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static gboolean
-is_printer_active (gpointer item, gpointer data)
-{
-  GtkPrinter *printer = item;
-  GtkPrintUnixDialog *dialog = data;
-  gboolean result;
-
-  result = gtk_printer_is_active (printer);
-
-  if (result &&
-      dialog->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
-                                   GTK_PRINT_CAPABILITY_GENERATE_PS))
-    {
-       /* Check that the printer can handle at least one of the data
-        * formats that the application supports.
-        */
-       result = ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
-                 gtk_printer_accepts_pdf (printer)) ||
-                ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
-                 gtk_printer_accepts_ps (printer));
-    }
-
-  return result;
-}
-
-static int
-default_printer_list_sort_func (gconstpointer a,
-                                gconstpointer b,
-                                gpointer      user_data)
-{
-  GtkPrinter *a_printer = (gpointer)a;
-  GtkPrinter *b_printer = (gpointer)b;
-  const char *a_name;
-  const char *b_name;
-
-  if (a_printer == NULL && b_printer == NULL)
-    return 0;
-  else if (a_printer == NULL)
-   return 1;
-  else if (b_printer == NULL)
-   return -1;
-
-  if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
-    return 0;
-  else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
-    return -1;
-  else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
-    return 1;
-
-  a_name = gtk_printer_get_name (a_printer);
-  b_name = gtk_printer_get_name (b_printer);
-
-  if (a_name == NULL && b_name == NULL)
-    return  0;
-  else if (a_name == NULL && b_name != NULL)
-    return  1;
-  else if (a_name != NULL && b_name == NULL)
-    return -1;
-
-  return g_ascii_strcasecmp (a_name, b_name);
-}
-
-static GtkWidget *
-wrap_in_frame (const char *label,
-               GtkWidget   *child)
-{
-  GtkWidget *box, *label_widget;
-  char *bold_text;
-
-  label_widget = gtk_label_new (NULL);
-  gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
-  gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
-
-  bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
-  gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
-  g_free (bold_text);
-
-  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-  gtk_box_append (GTK_BOX (box), label_widget);
-
-  gtk_widget_set_margin_start (child, 12);
-  gtk_widget_set_halign (child, GTK_ALIGN_FILL);
-  gtk_widget_set_valign (child, GTK_ALIGN_FILL);
-
-  gtk_box_append (GTK_BOX (box), child);
-
-  return box;
-}
-
-static gboolean
-setup_option (GtkPrintUnixDialog     *dialog,
-              const char             *option_name,
-              GtkPrinterOptionWidget *widget)
-{
-  GtkPrinterOption *option;
-
-  option = gtk_printer_option_set_lookup (dialog->options, option_name);
-  gtk_printer_option_widget_set_source (widget, option);
-
-  return option != NULL;
-}
-
-static void
-add_option_to_extension_point (GtkPrinterOption *option,
-                               gpointer          data)
-{
-  GtkWidget *extension_point = data;
-  GtkWidget *widget;
-
-  widget = gtk_printer_option_widget_new (option);
-
-  if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
-    {
-      GtkWidget *label, *hbox;
-
-      gtk_widget_set_valign (widget, GTK_ALIGN_BASELINE_FILL);
-
-      label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
-      gtk_widget_set_visible (label, TRUE);
-      gtk_widget_set_halign (label, GTK_ALIGN_START);
-      gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
-      gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
-
-      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-      gtk_widget_set_valign (hbox, GTK_ALIGN_BASELINE_FILL);
-      gtk_box_append (GTK_BOX (hbox), label);
-      gtk_box_append (GTK_BOX (hbox), widget);
-
-      gtk_box_append (GTK_BOX (extension_point), hbox);
-    }
-  else
-    gtk_box_append (GTK_BOX (extension_point), widget);
-}
-
-static int
-grid_rows (GtkGrid *table)
-{
-  int t0, t1, l, t, w, h;
-  GtkWidget *c;
-  gboolean first;
-
-  t0 = t1 = 0;
-  for (c = gtk_widget_get_first_child (GTK_WIDGET (table)), first = TRUE;
-       c != NULL;
-       c  = gtk_widget_get_next_sibling (GTK_WIDGET (c)), first = FALSE)
-    {
-      gtk_grid_query_child (table, c, &l, &t, &w, &h);
-      if (first)
-        {
-          t0 = t;
-          t1 = t + h;
-        }
-      else
-        {
-          if (t < t0)
-            t0 = t;
-          if (t + h > t1)
-            t1 = t + h;
-        }
-    }
-
-  return t1 - t0;
-}
-
-static void
-add_option_to_table (GtkPrinterOption *option,
-                     gpointer          user_data)
-{
-  GtkGrid *table;
-  GtkWidget *label, *widget;
-  guint row;
-
-  table = GTK_GRID (user_data);
-
-  if (g_str_has_prefix (option->name, "gtk-"))
-    return;
-
-  row = grid_rows (table);
-
-  widget = gtk_printer_option_widget_new (option);
-
-  if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
-    {
-      label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
-      gtk_widget_set_visible (label, TRUE);
-
-      gtk_widget_set_halign (label, GTK_ALIGN_START);
-      gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
-      gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
-
-      gtk_grid_attach (table, label, 0, row - 1, 1, 1);
-      gtk_grid_attach (table, widget, 1, row - 1, 1, 1);
-    }
-  else
-    gtk_grid_attach (table, widget, 0, row - 1, 2, 1);
-}
-
-static void
-setup_page_table (GtkPrinterOptionSet *options,
-                  const char          *group,
-                  GtkWidget           *table,
-                  GtkWidget           *page)
-{
-  int nrows;
-
-  gtk_printer_option_set_foreach_in_group (options, group,
-                                           add_option_to_table,
-                                           table);
-
-  nrows = grid_rows (GTK_GRID (table));
-  gtk_widget_set_visible (page, nrows > 0);
-}
-
-static void
-update_print_at_option (GtkPrintUnixDialog *dialog)
-{
-  GtkPrinterOption *option;
-
-  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
-
-  if (option == NULL)
-    return;
-
-  if (dialog->updating_print_at)
-    return;
-
-  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_at_radio)))
-    gtk_printer_option_set (option, "at");
-  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_hold_radio)))
-    gtk_printer_option_set (option, "on-hold");
-  else
-    gtk_printer_option_set (option, "now");
-
-  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
-  if (option != NULL)
-    {
-      const char *text;
-
-      text = gtk_editable_get_text (GTK_EDITABLE (dialog->print_at_entry));
-      gtk_printer_option_set (option, text);
-    }
-}
-
-
-static gboolean
-setup_print_at (GtkPrintUnixDialog *dialog)
-{
-  GtkPrinterOption *option;
-
-  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
-
-  if (option == NULL)
-    {
-      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
-      gtk_widget_set_sensitive (dialog->print_at_radio, FALSE);
-      gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
-      gtk_widget_set_sensitive (dialog->print_hold_radio, FALSE);
-      gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), "");
-      return FALSE;
-    }
-
-  dialog->updating_print_at = TRUE;
-
-  gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
-  gtk_widget_set_sensitive (dialog->print_at_radio,
-                            gtk_printer_option_has_choice (option, "at"));
-
-  gtk_widget_set_sensitive (dialog->print_hold_radio,
-                            gtk_printer_option_has_choice (option, "on-hold"));
-
-  update_print_at_option (dialog);
-
-  if (strcmp (option->value, "at") == 0)
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_at_radio), TRUE);
-  else if (strcmp (option->value, "on-hold") == 0)
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_hold_radio), TRUE);
-  else
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
-
-  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
-  if (option != NULL)
-    gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), option->value);
-
-  dialog->updating_print_at = FALSE;
-
-  return TRUE;
-}
-
-static void
-update_dialog_from_settings (GtkPrintUnixDialog *dialog)
-{
-  GList *groups, *l;
-  char *group;
-  GtkWidget *table, *frame;
-  gboolean has_advanced, has_job;
-  guint nrows;
-  GtkWidget *child;
-
-  if (dialog->current_printer == NULL)
-    {
-       clear_per_printer_ui (dialog);
-       gtk_widget_set_visible (dialog->job_page, FALSE);
-       gtk_widget_set_visible (dialog->advanced_page, FALSE);
-       gtk_widget_set_visible (dialog->image_quality_page, FALSE);
-       gtk_widget_set_visible (dialog->finishing_page, FALSE);
-       gtk_widget_set_visible (dialog->color_page, FALSE);
-       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
-
-       return;
-    }
-
-  setup_option (dialog, "gtk-n-up", dialog->pages_per_sheet);
-  setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
-  setup_option (dialog, "gtk-duplex", dialog->duplex);
-  setup_option (dialog, "gtk-paper-type", dialog->paper_type);
-  setup_option (dialog, "gtk-paper-source", dialog->paper_source);
-  setup_option (dialog, "gtk-output-tray", dialog->output_tray);
-
-  has_job = FALSE;
-  has_job |= setup_option (dialog, "gtk-job-prio", dialog->job_prio);
-  has_job |= setup_option (dialog, "gtk-billing-info", dialog->billing_info);
-  has_job |= setup_option (dialog, "gtk-cover-before", dialog->cover_before);
-  has_job |= setup_option (dialog, "gtk-cover-after", dialog->cover_after);
-  has_job |= setup_print_at (dialog);
-
-  gtk_widget_set_visible (dialog->job_page, has_job);
-
-  setup_page_table (dialog->options,
-                    "ImageQualityPage",
-                    dialog->image_quality_table,
-                    dialog->image_quality_page);
-
-  setup_page_table (dialog->options,
-                    "FinishingPage",
-                    dialog->finishing_table,
-                    dialog->finishing_page);
-
-  setup_page_table (dialog->options,
-                    "ColorPage",
-                    dialog->color_table,
-                    dialog->color_page);
-
-  gtk_printer_option_set_foreach_in_group (dialog->options,
-                                           "GtkPrintDialogExtension",
-                                           add_option_to_extension_point,
-                                           dialog->extension_point);
-
-  /* A bit of a hack, keep the last option flush right.
-   * This keeps the file format radios from moving as the
-   * filename changes.
-   */
-  child = gtk_widget_get_last_child (dialog->extension_point);
-  if (child && child != gtk_widget_get_first_child (dialog->extension_point))
-    gtk_widget_set_halign (child, GTK_ALIGN_END);
-
-  /* Put the rest of the groups in the advanced page */
-  groups = gtk_printer_option_set_get_groups (dialog->options);
-
-  has_advanced = FALSE;
-  for (l = groups; l != NULL; l = l->next)
-    {
-      group = l->data;
-
-      if (group == NULL)
-        continue;
-
-      if (strcmp (group, "ImageQualityPage") == 0 ||
-          strcmp (group, "ColorPage") == 0 ||
-          strcmp (group, "FinishingPage") == 0 ||
-          strcmp (group, "GtkPrintDialogExtension") == 0)
-        continue;
-
-      table = gtk_grid_new ();
-      gtk_grid_set_row_spacing (GTK_GRID (table), 6);
-      gtk_grid_set_column_spacing (GTK_GRID (table), 12);
-
-      gtk_printer_option_set_foreach_in_group (dialog->options,
-                                               group,
-                                               add_option_to_table,
-                                               table);
-
-      nrows = grid_rows (GTK_GRID (table));
-      if (nrows == 0)
-        {
-          g_object_unref (g_object_ref_sink (table));
-        }
-      else
-        {
-          has_advanced = TRUE;
-          frame = wrap_in_frame (group, table);
-          gtk_box_append (GTK_BOX (dialog->advanced_vbox), frame);
-        }
-    }
-
-  gtk_widget_set_visible (dialog->advanced_page, has_advanced);
-
-  g_list_free_full (groups, g_free);
-}
-
-static void
-update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
-{
-  GtkPrintCapabilities caps;
-  gboolean can_collate;
-  const char *copies;
-  GtkWidget *button;
-
-  copies = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
-  can_collate = (*copies != '\0' && atoi (copies) > 1);
-
-  caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
-  gtk_widget_set_sensitive (dialog->page_set_combo,
-                            caps & GTK_PRINT_CAPABILITY_PAGE_SET);
-  gtk_widget_set_sensitive (dialog->copies_spin,
-                            caps & GTK_PRINT_CAPABILITY_COPIES);
-  gtk_widget_set_sensitive (dialog->collate_check,
-                            can_collate &&
-                            (caps & GTK_PRINT_CAPABILITY_COLLATE));
-  gtk_widget_set_sensitive (dialog->reverse_check,
-                            caps & GTK_PRINT_CAPABILITY_REVERSE);
-  gtk_widget_set_sensitive (dialog->scale_spin,
-                            caps & GTK_PRINT_CAPABILITY_SCALE);
-  gtk_widget_set_sensitive (GTK_WIDGET (dialog->pages_per_sheet),
-                            caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
-
-  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
-  gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0);
-
-  update_collate_icon (NULL, dialog);
-}
-
-static gboolean
-page_setup_is_equal (GtkPageSetup *a,
-                     GtkPageSetup *b)
-{
-  return
-    gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
-                             gtk_page_setup_get_paper_size (b)) &&
-    gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
-    gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
-}
-
-static gboolean
-page_setup_is_same_size (GtkPageSetup *a,
-                         GtkPageSetup *b)
-{
-  return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
-                                  gtk_page_setup_get_paper_size (b));
-}
-
-static gboolean
-set_paper_size (GtkPrintUnixDialog *dialog,
-                GtkPageSetup       *page_setup,
-                gboolean            size_only,
-                gboolean            add_item)
-{
-  GListModel *model;
-  GtkPageSetup *list_page_setup;
-  guint i;
-
-  if (!dialog->internal_page_setup_change)
-    return TRUE;
-
-  if (page_setup == NULL)
-    return FALSE;
-
-  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
-  for (i = 0; i < g_list_model_get_n_items (model); i++)
-    {
-      list_page_setup = g_list_model_get_item (model, i);
-      if (list_page_setup == NULL)
-        continue;
-
-      if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
-          (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
-        {
-          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
-          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
-                                      gtk_page_setup_get_orientation (page_setup));
-          g_object_unref (list_page_setup);
-          return TRUE;
-        }
-
-      g_object_unref (list_page_setup);
-    }
-
-  if (add_item)
-    {
-      i = g_list_model_get_n_items (model);
-      g_list_store_append (dialog->page_setup_list, page_setup);
-      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
-      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
-                                  gtk_page_setup_get_orientation (page_setup));
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
-{
-  g_list_store_remove_all (dialog->custom_paper_list);
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-}
-
-static void
-fill_paper_sizes (GtkPrintUnixDialog *dialog,
-                  GtkPrinter         *printer)
-{
-  GList *list, *l;
-  GtkPageSetup *page_setup;
-  GtkPaperSize *paper_size;
-  int i;
-
-  g_list_store_remove_all (dialog->page_setup_list);
-
-  if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
-    {
-      for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
-        {
-          page_setup = gtk_page_setup_new ();
-          paper_size = gtk_paper_size_new (common_paper_sizes[i]);
-          gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
-          gtk_paper_size_free (paper_size);
-          g_list_store_append (dialog->page_setup_list, page_setup);
-          g_object_unref (page_setup);
-        }
-    }
-  else
-    {
-      for (l = list; l != NULL; l = l->next)
-        {
-          page_setup = l->data;
-          g_list_store_append (dialog->page_setup_list, page_setup);
-          g_object_unref (page_setup);
-        }
-      g_list_free (list);
-    }
-}
-
-static void
-update_paper_sizes (GtkPrintUnixDialog *dialog)
-{
-  GtkPageSetup *current_page_setup = NULL;
-  GtkPrinter   *printer;
-
-  printer = gtk_print_unix_dialog_get_selected_printer (dialog);
-
-  fill_paper_sizes (dialog, printer);
-  fill_custom_paper_sizes (dialog);
-
-  current_page_setup = gtk_page_setup_copy (gtk_print_unix_dialog_get_page_setup (dialog));
-
-  if (current_page_setup)
-    {
-      if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
-        set_paper_size (dialog, current_page_setup, TRUE, TRUE);
-
-      g_object_unref (current_page_setup);
-    }
-}
-
-static void
-mark_conflicts (GtkPrintUnixDialog *dialog)
-{
-  GtkPrinter *printer;
-  gboolean have_conflict;
-
-  have_conflict = FALSE;
-
-  printer = dialog->current_printer;
-
-  if (printer)
-    {
-      g_signal_handler_block (dialog->options, dialog->options_changed_handler);
-
-      gtk_printer_option_set_clear_conflicts (dialog->options);
-      have_conflict = _gtk_printer_mark_conflicts (printer, dialog->options);
-
-      g_signal_handler_unblock (dialog->options, dialog->options_changed_handler);
-    }
-
-  gtk_widget_set_visible (dialog->conflicts_widget, have_conflict);
-}
-
-static gboolean
-mark_conflicts_callback (gpointer data)
-{
-  GtkPrintUnixDialog *dialog = data;
-
-  dialog->mark_conflicts_id = 0;
-
-  mark_conflicts (dialog);
-
-  return FALSE;
-}
-
-static void
-unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
-{
-  if (dialog->mark_conflicts_id != 0)
-    {
-      g_source_remove (dialog->mark_conflicts_id);
-      dialog->mark_conflicts_id = 0;
-    }
-}
-
-static void
-schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
-{
-  if (dialog->mark_conflicts_id != 0)
-    return;
-
-  dialog->mark_conflicts_id = g_idle_add (mark_conflicts_callback, dialog);
-  gdk_source_set_static_name_by_id (dialog->mark_conflicts_id, "[gtk] mark_conflicts_callback");
-}
-
-static void
-options_changed_cb (GtkPrintUnixDialog *dialog)
-{
-  schedule_idle_mark_conflicts (dialog);
-
-  g_free (dialog->waiting_for_printer);
-  dialog->waiting_for_printer = NULL;
-}
-
-static void
-clear_per_printer_ui (GtkPrintUnixDialog *dialog)
-{
-  GtkWidget *child;
-
-  if (dialog->finishing_table == NULL)
-    return;
-
-  while ((child = gtk_widget_get_first_child (dialog->finishing_table)))
-    gtk_grid_remove (GTK_GRID (dialog->finishing_table), child);
-  while ((child = gtk_widget_get_first_child (dialog->image_quality_table)))
-    gtk_grid_remove (GTK_GRID (dialog->image_quality_table), child);
-  while ((child = gtk_widget_get_first_child (dialog->color_table)))
-    gtk_grid_remove (GTK_GRID (dialog->color_table), child);
-  while ((child = gtk_widget_get_first_child (dialog->advanced_vbox)))
-    gtk_box_remove (GTK_BOX (dialog->advanced_vbox), child);
-  while ((child = gtk_widget_get_first_child (dialog->extension_point)))
-    gtk_box_remove (GTK_BOX (dialog->extension_point), child);
-}
-
-static void
-printer_details_acquired (GtkPrinter         *printer,
-                          gboolean            success,
-                          GtkPrintUnixDialog *dialog)
-{
-  disconnect_printer_details_request (dialog, !success);
-
-  if (success)
-    selected_printer_changed (dialog);
-}
-
-static void
-selected_printer_changed (GtkPrintUnixDialog *dialog)
-{
-  GListModel *model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
-  GtkPrinter *printer;
-
-  /* Whenever the user selects a printer we stop looking for
-   * the printer specified in the initial settings
-   */
-  if (dialog->waiting_for_printer &&
-      !dialog->internal_printer_change)
-    {
-      g_free (dialog->waiting_for_printer);
-      dialog->waiting_for_printer = NULL;
-    }
-
-  disconnect_printer_details_request (dialog, FALSE);
-
-  printer = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
-
-  /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
-   * accepts/rejects jobs
-   */
-  if (printer != NULL)
-    {
-      if (!gtk_printer_is_accepting_jobs (printer))
-        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
-      else if (dialog->current_printer == printer && gtk_printer_has_details (printer))
-        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
-    }
-
-  if (printer != NULL && !gtk_printer_has_details (printer))
-    {
-      gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
-      dialog->request_details_tag = g_signal_connect (printer, "details-acquired",
-                                                      G_CALLBACK (printer_details_acquired), dialog);
-
-      dialog->request_details_printer = g_object_ref (printer);
-      set_busy_cursor (dialog, TRUE);
-      gtk_printer_set_state_message (printer, _("Getting printer information…"));
-      gtk_printer_request_details (printer);
-      return;
-    }
-
-  if (printer == dialog->current_printer)
-    return;
-
-  if (dialog->options)
-    {
-      g_clear_object (&dialog->options);
-      clear_per_printer_ui (dialog);
-    }
-
-  g_clear_object (&dialog->current_printer);
-  dialog->printer_capabilities = 0;
-
-  if (printer != NULL && gtk_printer_is_accepting_jobs (printer))
-    gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
-  dialog->current_printer = g_object_ref (printer);
-
-  if (printer != NULL)
-    {
-      if (!dialog->page_setup_set)
-        {
-          /* if no explicit page setup has been set, use the printer default */
-          GtkPageSetup *page_setup;
-
-          page_setup = gtk_printer_get_default_page_size (printer);
-
-          if (!page_setup)
-            page_setup = gtk_page_setup_new ();
-
-          if (page_setup && dialog->page_setup)
-            gtk_page_setup_set_orientation (page_setup, gtk_page_setup_get_orientation (dialog->page_setup));
-
-          g_clear_object (&dialog->page_setup);
-          dialog->page_setup = page_setup; /* transfer ownership */
-        }
-
-      dialog->printer_capabilities = gtk_printer_get_capabilities (printer);
-      dialog->options = _gtk_printer_get_options (printer,
-                                                dialog->initial_settings,
-                                                dialog->page_setup,
-                                                dialog->manual_capabilities);
-
-      dialog->options_changed_handler =
-        g_signal_connect_swapped (dialog->options, "changed", G_CALLBACK (options_changed_cb), dialog);
-      schedule_idle_mark_conflicts (dialog);
-    }
-
-  update_dialog_from_settings (dialog);
-  update_dialog_from_capabilities (dialog);
-
-  dialog->internal_page_setup_change = TRUE;
-  update_paper_sizes (dialog);
-  dialog->internal_page_setup_change = FALSE;
-
-  g_object_notify (G_OBJECT (dialog), "selected-printer");
-}
-
-static void
-update_collate_icon (GtkToggleButton    *toggle_button,
-                     GtkPrintUnixDialog *dialog)
-{
-  gtk_widget_queue_draw (dialog->collate_image);
-}
-
-static void
-paint_page (GtkPrintUnixDialog *dialog,
-            GtkWidget  *widget,
-            cairo_t    *cr,
-            int         x,
-            int         y,
-            const char *text,
-            int         text_x)
-{
-  GtkCssStyle *style;
-  int width, height;
-  int text_y;
-  GdkRGBA color;
-  GtkSnapshot *snapshot;
-  GskRenderNode *node;
-  GtkCssBoxes boxes;
-
-  width = 20;
-  height = 26;
-  text_y = 21;
-
-  style = gtk_css_node_get_style (dialog->collate_paper_node);
-
-  snapshot = gtk_snapshot_new ();
-  gtk_css_boxes_init_border_box (&boxes, style, x, y, width, height);
-  gtk_css_style_snapshot_background (&boxes, snapshot);
-  gtk_css_style_snapshot_border (&boxes, snapshot);
-
-  node = gtk_snapshot_free_to_node (snapshot);
-  if (node)
-    {
-      gsk_render_node_draw (node, cr);
-      gsk_render_node_unref (node);
-    }
-
-  color = *gtk_css_color_value_get_rgba (style->core->color);
-  gdk_cairo_set_source_rgba (cr, &color);
-
-  cairo_select_font_face (cr, "Sans",
-                          CAIRO_FONT_SLANT_NORMAL,
-                          CAIRO_FONT_WEIGHT_NORMAL);
-  cairo_set_font_size (cr, 9);
-  cairo_move_to (cr, x + text_x, y + text_y);
-  cairo_show_text (cr, text);
-}
-
-static void
-draw_collate (GtkDrawingArea *da,
-              cairo_t        *cr,
-              int             width,
-              int             height,
-              gpointer        data)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
-  GtkWidget *widget = GTK_WIDGET (da);
-  gboolean collate, reverse, rtl;
-  int copies;
-  int text_x;
-  int x, y, x1, x2, p1, p2;
-
-  collate = dialog_get_collate (dialog);
-  reverse = dialog_get_reverse (dialog);
-  copies = dialog_get_n_copies (dialog);
-
-  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
-
-  x = (width - 30) / 2;
-  y = (height - 36) / 2;
-  if (rtl)
-    {
-      x1 = x;
-      x2 = x - 36;
-      p1 = 0;
-      p2 = 10;
-      text_x = 4;
-    }
-  else
-    {
-      x1 = x;
-      x2 = x + 36;
-      p1 = 10;
-      p2 = 0;
-      text_x = 11;
-    }
-
-  if (copies == 1)
-    {
-      paint_page (dialog, widget, cr, x1 + p1, y, reverse ? "1" : "2", text_x);
-      paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
-    }
-  else
-    {
-      paint_page (dialog, widget, cr, x1 + p1, y, collate == reverse ? "1" : "2", text_x);
-      paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
-
-      paint_page (dialog, widget, cr, x2 + p1, y, reverse ? "1" : "2", text_x);
-      paint_page (dialog, widget, cr, x2 + p2, y + 10, collate == reverse ? "2" : "1", text_x);
-    }
-}
-
-static gboolean
-page_range_entry_focus_changed (GtkWidget          *entry,
-                                GParamSpec         *pspec,
-                                GtkPrintUnixDialog *dialog)
-{
-  if (gtk_widget_has_focus (entry))
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
-
-  return FALSE;
-}
-
-static void
-update_page_range_entry_sensitivity (GtkWidget *button,
-                                    GtkPrintUnixDialog *dialog)
-{
-  gboolean active;
-
-  active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
-
-  if (active)
-    gtk_widget_grab_focus (dialog->page_range_entry);
-}
-
-static void
-update_print_at_entry_sensitivity (GtkWidget *button,
-                                  GtkPrintUnixDialog *dialog)
-{
-  gboolean active;
-
-  active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
-
-  gtk_widget_set_sensitive (dialog->print_at_entry, active);
-
-  if (active)
-    gtk_widget_grab_focus (dialog->print_at_entry);
-}
-
-static gboolean
-is_range_separator (char c)
-{
-  return (c == ',' || c == ';' || c == ':');
-}
-
-static GtkPageRange *
-dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
-                        int                *n_ranges_out)
-{
-  int i, n_ranges;
-  const char *text, *p;
-  char *next;
-  GtkPageRange *ranges;
-  int start, end;
-
-  text = gtk_editable_get_text (GTK_EDITABLE (dialog->page_range_entry));
-
-  if (*text == 0)
-    {
-      *n_ranges_out = 0;
-      return NULL;
-    }
-
-  n_ranges = 1;
-  p = text;
-  while (*p)
-    {
-      if (is_range_separator (*p))
-        n_ranges++;
-      p++;
-    }
-
-  ranges = g_new0 (GtkPageRange, n_ranges);
-
-  i = 0;
-  p = text;
-  while (*p)
-    {
-      while (isspace (*p)) p++;
-
-      if (*p == '-')
-        {
-          /* a half-open range like -2 */
-          start = 1;
-        }
-      else
-        {
-          start = (int)strtol (p, &next, 10);
-          if (start < 1)
-            start = 1;
-          p = next;
-        }
-
-      end = start;
-
-      while (isspace (*p)) p++;
-
-      if (*p == '-')
-        {
-          p++;
-          end = (int)strtol (p, &next, 10);
-          if (next == p) /* a half-open range like 2- */
-            end = 0;
-          else if (end < start)
-            end = start;
-        }
-
-      ranges[i].start = start - 1;
-      ranges[i].end = end - 1;
-      i++;
-
-      /* Skip until end or separator */
-      while (*p && !is_range_separator (*p))
-        p++;
-
-      /* if not at end, skip separator */
-      if (*p)
-        p++;
-    }
-
-  *n_ranges_out = i;
-
-  return ranges;
-}
-
-static void
-dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
-                        GtkPageRange       *ranges,
-                        int                 n_ranges)
-{
-  int i;
-  GString *s = g_string_new (NULL);
-
-  for (i = 0; i < n_ranges; i++)
-    {
-      g_string_append_printf (s, "%d", ranges[i].start + 1);
-      if (ranges[i].end > ranges[i].start)
-        g_string_append_printf (s, "-%d", ranges[i].end + 1);
-      else if (ranges[i].end == -1)
-        g_string_append (s, "-");
-
-      if (i != n_ranges - 1)
-        g_string_append (s, ",");
-    }
-
-  gtk_editable_set_text (GTK_EDITABLE (dialog->page_range_entry), s->str);
-
-  g_string_free (s, TRUE);
-}
-
-static GtkPrintPages
-dialog_get_print_pages (GtkPrintUnixDialog *dialog)
-{
-  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->all_pages_radio)))
-    return GTK_PRINT_PAGES_ALL;
-  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->current_page_radio)))
-    return GTK_PRINT_PAGES_CURRENT;
-  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->selection_radio)))
-    return GTK_PRINT_PAGES_SELECTION;
-  else
-    return GTK_PRINT_PAGES_RANGES;
-}
-
-static void
-dialog_set_print_pages (GtkPrintUnixDialog *dialog,
-                        GtkPrintPages       pages)
-{
-  if (pages == GTK_PRINT_PAGES_RANGES)
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
-  else if (pages == GTK_PRINT_PAGES_CURRENT)
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->current_page_radio), TRUE);
-  else if (pages == GTK_PRINT_PAGES_SELECTION)
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->selection_radio), TRUE);
-  else
-    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->all_pages_radio), TRUE);
-}
-
-static double
-dialog_get_scale (GtkPrintUnixDialog *dialog)
-{
-  if (gtk_widget_is_sensitive (dialog->scale_spin))
-    return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->scale_spin));
-  else
-    return 100.0;
-}
-
-static void
-dialog_set_scale (GtkPrintUnixDialog *dialog,
-                  double              val)
-{
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), val);
-}
-
-static GtkPageSet
-dialog_get_page_set (GtkPrintUnixDialog *dialog)
-{
-  if (gtk_widget_is_sensitive (dialog->page_set_combo))
-    return (GtkPageSet)gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->page_set_combo));
-  else
-    return GTK_PAGE_SET_ALL;
-}
-
-static void
-dialog_set_page_set (GtkPrintUnixDialog *dialog,
-                     GtkPageSet          val)
-{
-  gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->page_set_combo), (guint)val);
-}
-
-static int
-dialog_get_n_copies (GtkPrintUnixDialog *dialog)
-{
-  GtkAdjustment *adjustment;
-  const char *text;
-  char *endptr = NULL;
-  int n_copies;
-
-  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (dialog->copies_spin));
-
-  text = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
-  n_copies = g_ascii_strtoull (text, &endptr, 0);
-
-  if (gtk_widget_is_sensitive (dialog->copies_spin))
-    {
-      if (n_copies != 0 && endptr != text && (endptr != NULL && endptr[0] == '\0') &&
-          n_copies >= gtk_adjustment_get_lower (adjustment) &&
-          n_copies <= gtk_adjustment_get_upper (adjustment))
-        {
-          return n_copies;
-        }
-
-      return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->copies_spin));
-    }
-
-  return 1;
-}
-
-static void
-dialog_set_n_copies (GtkPrintUnixDialog *dialog,
-                     int                 n_copies)
-{
-  gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->copies_spin), n_copies);
-}
-
-static gboolean
-dialog_get_collate (GtkPrintUnixDialog *dialog)
-{
-  if (gtk_widget_is_sensitive (dialog->collate_check))
-    return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->collate_check));
-  return FALSE;
-}
-
-static void
-dialog_set_collate (GtkPrintUnixDialog *dialog,
-                    gboolean            collate)
-{
-  gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), collate);
-}
-
-static gboolean
-dialog_get_reverse (GtkPrintUnixDialog *dialog)
-{
-  if (gtk_widget_is_sensitive (dialog->reverse_check))
-    return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_check));
-  return FALSE;
-}
-
-static void
-dialog_set_reverse (GtkPrintUnixDialog *dialog,
-                    gboolean            reverse)
-{
-  gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), reverse);
-}
-
-static int
-dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
-{
-  const char *val;
-  int num;
-
-  val = gtk_printer_option_widget_get_value (dialog->pages_per_sheet);
-
-  num = 1;
-
-  if (val)
-    {
-      num = atoi(val);
-      if (num < 1)
-        num = 1;
-    }
-
-  return num;
-}
-
-static GtkNumberUpLayout
-dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
-{
-  GtkPrintCapabilities       caps;
-  GtkNumberUpLayout          layout;
-  const char                *val;
-  GEnumClass                *enum_class;
-  GEnumValue                *enum_value;
-
-  val = gtk_printer_option_widget_get_value (dialog->number_up_layout);
-
-  caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
-  if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
-    return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-
-  if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
-    layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-  else
-    layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
-
-  if (val == NULL)
-    return layout;
-
-  if (val[0] == '\0' && dialog->options)
-    {
-      GtkPrinterOption *option = gtk_printer_option_set_lookup (dialog->options, "gtk-n-up-layout");
-      if (option)
-        val = option->value;
-    }
-
-  enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
-  enum_value = g_enum_get_value_by_nick (enum_class, val);
-  if (enum_value)
-    layout = enum_value->value;
-  g_type_class_unref (enum_class);
-
-  return layout;
-}
-
-static void
-draw_page (GtkDrawingArea *da,
-           cairo_t        *cr,
-           int             width,
-           int             height,
-           gpointer        data)
-{
-  GtkWidget *widget = GTK_WIDGET (da);
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
-  GtkCssStyle *style;
-  double ratio;
-  int w, h, tmp;
-  int pages_x, pages_y, i, x, y, layout_w, layout_h;
-  double page_width, page_height;
-  GtkPageOrientation orientation;
-  gboolean landscape;
-  PangoLayout *layout;
-  PangoFontDescription *font;
-  char *text;
-  GdkRGBA color;
-  GtkNumberUpLayout number_up_layout;
-  int start_x, end_x, start_y, end_y;
-  int dx, dy;
-  gboolean horizontal;
-  GtkPageSetup *page_setup;
-  double paper_width, paper_height;
-  double pos_x, pos_y;
-  int pages_per_sheet;
-  gboolean ltr = TRUE;
-  GtkSnapshot *snapshot;
-  GtkCssBoxes boxes;
-  GskRenderNode *node;
-
-  orientation = gtk_page_setup_get_orientation (dialog->page_setup);
-  landscape =
-    (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
-    (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
-
-  number_up_layout = dialog_get_number_up_layout (dialog);
-
-  cairo_save (cr);
-
-  page_setup = gtk_print_unix_dialog_get_page_setup (dialog);
-
-  if (page_setup != NULL)
-    {
-      if (!landscape)
-        {
-          paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
-          paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
-        }
-      else
-        {
-          paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
-          paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
-        }
-
-      if (paper_width < paper_height)
-        {
-          h = EXAMPLE_PAGE_AREA_SIZE - 3;
-          w = (paper_height != 0) ? h * paper_width / paper_height : 0;
-        }
-      else
-        {
-          w = EXAMPLE_PAGE_AREA_SIZE - 3;
-          h = (paper_width != 0) ? w * paper_height / paper_width : 0;
-        }
-
-      if (paper_width == 0)
-        w = 0;
-
-      if (paper_height == 0)
-        h = 0;
-    }
-  else
-    {
-      ratio = G_SQRT2;
-      w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
-      h = EXAMPLE_PAGE_AREA_SIZE - 3;
-    }
-
-  pages_per_sheet = dialog_get_pages_per_sheet (dialog);
-  switch (pages_per_sheet)
-    {
-    default:
-    case 1:
-      pages_x = 1; pages_y = 1;
-      break;
-    case 2:
-      landscape = !landscape;
-      pages_x = 1; pages_y = 2;
-      break;
-    case 4:
-      pages_x = 2; pages_y = 2;
-      break;
-    case 6:
-      landscape = !landscape;
-      pages_x = 2; pages_y = 3;
-      break;
-    case 9:
-      pages_x = 3; pages_y = 3;
-      break;
-    case 16:
-      pages_x = 4; pages_y = 4;
-      break;
-    }
-
-  if (landscape)
-    {
-      tmp = w;
-      w = h;
-      h = tmp;
-
-      tmp = pages_x;
-      pages_x = pages_y;
-      pages_y = tmp;
-    }
-
-  style = gtk_css_node_get_style (dialog->page_layout_paper_node);
-  color = *gtk_css_color_value_get_rgba (style->core->color);
-
-  pos_x = (width - w) / 2;
-  pos_y = (height - h) / 2 - 10;
-  cairo_translate (cr, pos_x, pos_y);
-
-  snapshot = gtk_snapshot_new ();
-  gtk_css_boxes_init_border_box (&boxes, style, 1, 1, w, h);
-  gtk_css_style_snapshot_background (&boxes, snapshot);
-  gtk_css_style_snapshot_border (&boxes, snapshot);
-
-  node = gtk_snapshot_free_to_node (snapshot);
-  if (node)
-    {
-      gsk_render_node_draw (node, cr);
-      gsk_render_node_unref (node);
-    }
-
-  cairo_set_line_width (cr, 1.0);
-
-  i = 1;
-
-  page_width = (double)w / pages_x;
-  page_height = (double)h / pages_y;
-
-  layout  = pango_cairo_create_layout (cr);
-
-  font = pango_font_description_new ();
-  pango_font_description_set_family (font, "sans");
-
-  if (page_height > 0)
-    pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
-  else
-    pango_font_description_set_absolute_size (font, 1);
-
-  pango_layout_set_font_description (layout, font);
-  pango_font_description_free (font);
-
-  pango_layout_set_width (layout, page_width * PANGO_SCALE);
-  pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
-  switch (number_up_layout)
-    {
-      default:
-      case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
-        start_x = 0;
-        end_x = pages_x - 1;
-        start_y = 0;
-        end_y = pages_y - 1;
-        dx = 1;
-        dy = 1;
-        horizontal = TRUE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
-        start_x = 0;
-        end_x = pages_x - 1;
-        start_y = pages_y - 1;
-        end_y = 0;
-        dx = 1;
-        dy = - 1;
-        horizontal = TRUE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
-        start_x = pages_x - 1;
-        end_x = 0;
-        start_y = 0;
-        end_y = pages_y - 1;
-        dx = - 1;
-        dy = 1;
-        horizontal = TRUE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
-        start_x = pages_x - 1;
-        end_x = 0;
-        start_y = pages_y - 1;
-        end_y = 0;
-        dx = - 1;
-        dy = - 1;
-        horizontal = TRUE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
-        start_x = 0;
-        end_x = pages_x - 1;
-        start_y = 0;
-        end_y = pages_y - 1;
-        dx = 1;
-        dy = 1;
-        horizontal = FALSE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
-        start_x = pages_x - 1;
-        end_x = 0;
-        start_y = 0;
-        end_y = pages_y - 1;
-        dx = - 1;
-        dy = 1;
-        horizontal = FALSE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
-        start_x = 0;
-        end_x = pages_x - 1;
-        start_y = pages_y - 1;
-        end_y = 0;
-        dx = 1;
-        dy = - 1;
-        horizontal = FALSE;
-        break;
-      case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
-        start_x = pages_x - 1;
-        end_x = 0;
-        start_y = pages_y - 1;
-        end_y = 0;
-        dx = - 1;
-        dy = - 1;
-        horizontal = FALSE;
-        break;
-    }
-
-  gdk_cairo_set_source_rgba (cr, &color);
-  if (horizontal)
-    for (y = start_y; y != end_y + dy; y += dy)
-      {
-        for (x = start_x; x != end_x + dx; x += dx)
-          {
-            text = g_strdup_printf ("%d", i++);
-            pango_layout_set_text (layout, text, -1);
-            g_free (text);
-            pango_layout_get_size (layout, &layout_w, &layout_h);
-            cairo_save (cr);
-            cairo_translate (cr,
-                             x * page_width,
-                             y * page_height + (page_height - layout_h / 1024.0) / 2);
-
-            pango_cairo_show_layout (cr, layout);
-            cairo_restore (cr);
-          }
-      }
-  else
-    for (x = start_x; x != end_x + dx; x += dx)
-      {
-        for (y = start_y; y != end_y + dy; y += dy)
-          {
-            text = g_strdup_printf ("%d", i++);
-            pango_layout_set_text (layout, text, -1);
-            g_free (text);
-            pango_layout_get_size (layout, &layout_w, &layout_h);
-            cairo_save (cr);
-            cairo_translate (cr,
-                             x * page_width,
-                             y * page_height + (page_height - layout_h / 1024.0) / 2);
-
-            pango_cairo_show_layout (cr, layout);
-            cairo_restore (cr);
-          }
-      }
-
-  g_object_unref (layout);
-
-  style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
-  color = *gtk_css_color_value_get_rgba (style->core->color);
-
-  if (page_setup != NULL)
-    {
-      PangoContext *pango_c = NULL;
-      PangoFontDescription *pango_f = NULL;
-      int font_size = 12 * PANGO_SCALE;
-
-      pos_x += 1;
-      pos_y += 1;
-
-      if (pages_per_sheet == 2 || pages_per_sheet == 6)
-        {
-          paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
-          paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
-        }
-      else
-        {
-          paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
-          paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
-        }
-
-      cairo_restore (cr);
-      cairo_save (cr);
-
-      layout = pango_cairo_create_layout (cr);
-
-      font = pango_font_description_new ();
-      pango_font_description_set_family (font, "sans");
-
-      pango_c = gtk_widget_get_pango_context (widget);
-      if (pango_c != NULL)
-        {
-          pango_f = pango_context_get_font_description (pango_c);
-          if (pango_f != NULL)
-            font_size = pango_font_description_get_size (pango_f);
-        }
-
-      pango_font_description_set_size (font, font_size);
-      pango_layout_set_font_description (layout, font);
-      pango_font_description_free (font);
-
-      pango_layout_set_width (layout, -1);
-      pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-
-      if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
-        text = g_strdup_printf ("%.1f mm", paper_height);
-      else
-        text = g_strdup_printf ("%.2f inch", paper_height);
-
-      pango_layout_set_text (layout, text, -1);
-      g_free (text);
-      pango_layout_get_size (layout, &layout_w, &layout_h);
-
-      ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
-
-      if (ltr)
-        cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
-                             (height - layout_h / PANGO_SCALE) / 2);
-      else
-        cairo_translate (cr, pos_x + w + 2 * RULER_DISTANCE,
-                             (height - layout_h / PANGO_SCALE) / 2);
-
-      gdk_cairo_set_source_rgba (cr, &color);
-      pango_cairo_show_layout (cr, layout);
-
-      cairo_restore (cr);
-      cairo_save (cr);
-
-      if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
-        text = g_strdup_printf ("%.1f mm", paper_width);
-      else
-        text = g_strdup_printf ("%.2f inch", paper_width);
-
-      pango_layout_set_text (layout, text, -1);
-      g_free (text);
-      pango_layout_get_size (layout, &layout_w, &layout_h);
-
-      cairo_translate (cr, (width - layout_w / PANGO_SCALE) / 2,
-                           pos_y + h + 2 * RULER_DISTANCE);
-
-      gdk_cairo_set_source_rgba (cr, &color);
-      pango_cairo_show_layout (cr, layout);
-
-      g_object_unref (layout);
-
-      cairo_restore (cr);
-
-      cairo_set_line_width (cr, 1);
-
-      gdk_cairo_set_source_rgba (cr, &color);
-
-      if (ltr)
-        {
-          cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
-          cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
-          cairo_stroke (cr);
-
-          cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
-          cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
-          cairo_stroke (cr);
-
-          cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
-          cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
-          cairo_stroke (cr);
-        }
-      else
-        {
-          cairo_move_to (cr, pos_x + w + RULER_DISTANCE, pos_y);
-          cairo_line_to (cr, pos_x + w + RULER_DISTANCE, pos_y + h);
-          cairo_stroke (cr);
-
-          cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
-          cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
-          cairo_stroke (cr);
-
-          cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
-          cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
-          cairo_stroke (cr);
-        }
-
-      cairo_move_to (cr, pos_x, pos_y + h + RULER_DISTANCE);
-      cairo_line_to (cr, pos_x + w, pos_y + h + RULER_DISTANCE);
-      cairo_stroke (cr);
-
-      cairo_move_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
-      cairo_line_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
-      cairo_stroke (cr);
-
-      cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
-      cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
-      cairo_stroke (cr);
-    }
-}
-
-static void
-redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
-{
-  if (dialog->page_layout_preview)
-    gtk_widget_queue_draw (dialog->page_layout_preview);
-}
-
-static void
-update_number_up_layout (GtkPrintUnixDialog *dialog)
-{
-  GtkPrintCapabilities       caps;
-  GtkPrinterOptionSet       *set;
-  GtkNumberUpLayout          layout;
-  GtkPrinterOption          *option;
-  GtkPrinterOption          *old_option;
-  GtkPageOrientation         page_orientation;
-
-  set = dialog->options;
-
-  caps = dialog->manual_capabilities | dialog->printer_capabilities;
-
-  if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
-    {
-      if (dialog->number_up_layout_n_option == NULL)
-        {
-          dialog->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
-          if (dialog->number_up_layout_n_option == NULL)
-            {
-              const char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
-               /* Translators: These strings name the possible arrangements of
-                * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
-                */
-              const char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
-                                                    N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
-                                                    N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
-                                                    N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
-              int i;
-
-              dialog->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
-                                                                        _("Page Ordering"),
-                                                                        GTK_PRINTER_OPTION_TYPE_PICKONE);
-              gtk_printer_option_allocate_choices (dialog->number_up_layout_n_option, 8);
-
-              for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
-                {
-                  dialog->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
-                  dialog->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
-                }
-            }
-          g_object_ref (dialog->number_up_layout_n_option);
-
-          dialog->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
-                                                                    _("Page Ordering"),
-                                                                    GTK_PRINTER_OPTION_TYPE_PICKONE);
-          gtk_printer_option_allocate_choices (dialog->number_up_layout_2_option, 2);
-        }
-
-      page_orientation = gtk_page_setup_get_orientation (dialog->page_setup);
-      if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-          page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-        {
-          if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
-                 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[2]))
-            {
-              g_free (dialog->number_up_layout_2_option->choices_display[0]);
-              g_free (dialog->number_up_layout_2_option->choices_display[1]);
-              dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
-              dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[2];
-              dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
-              dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
-            }
-        }
-      else
-        {
-          if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
-                 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[1]))
-            {
-              g_free (dialog->number_up_layout_2_option->choices_display[0]);
-              g_free (dialog->number_up_layout_2_option->choices_display[1]);
-              dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
-              dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[1];
-              dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
-              dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
-            }
-        }
-
-      layout = dialog_get_number_up_layout (dialog);
-
-      old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
-      if (old_option != NULL)
-        gtk_printer_option_set_remove (set, old_option);
-
-      if (dialog_get_pages_per_sheet (dialog) != 1)
-        {
-          GEnumClass *enum_class;
-          GEnumValue *enum_value;
-          enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
-
-          if (dialog_get_pages_per_sheet (dialog) == 2)
-            {
-              option = dialog->number_up_layout_2_option;
-
-              switch (layout)
-                {
-                case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
-                case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
-                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
-                  break;
-
-                case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
-                case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
-                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
-                  break;
-
-                case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
-                case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
-                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
-                  break;
-
-                case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
-                case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
-                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
-                  break;
-
-                default:
-                  g_assert_not_reached();
-                  enum_value = NULL;
-                }
-            }
-          else
-            {
-              option = dialog->number_up_layout_n_option;
-
-              enum_value = g_enum_get_value (enum_class, layout);
-            }
-
-          g_assert (enum_value != NULL);
-          gtk_printer_option_set (option, enum_value->value_nick);
-          g_type_class_unref (enum_class);
-
-          gtk_printer_option_set_add (set, option);
-        }
-    }
-
-  setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
-
-  if (dialog->number_up_layout != NULL)
-    gtk_widget_set_sensitive (GTK_WIDGET (dialog->number_up_layout),
-                              (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
-                              (dialog_get_pages_per_sheet (dialog) > 1));
-}
-
-static void
-custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
-                                 int        response_id,
-                                 gpointer   user_data)
-{
-  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (user_data);
-
-  dialog->internal_page_setup_change = TRUE;
-  gtk_print_load_custom_papers (dialog->custom_paper_list);
-  update_paper_sizes (dialog);
-  dialog->internal_page_setup_change = FALSE;
-
-  if (dialog->page_setup_set)
-    {
-      GListModel *model;
-      guint n, i;
-
-      model = G_LIST_MODEL (dialog->custom_paper_list);
-      n = g_list_model_get_n_items (model);
-      for (i = 0; i < n; i++)
-        {
-          GtkPageSetup *page_setup = g_list_model_get_item (model, i);
-
-          if (g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
-                         gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (dialog->page_setup))) == 0)
-            gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
-
-          g_clear_object (&page_setup);
-        }
-    }
-
-  gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
-}
-
-static void
-orientation_changed (GObject            *object,
-                     GParamSpec         *pspec,
-                     GtkPrintUnixDialog *dialog)
-{
-  GtkPageOrientation orientation;
-  GtkPageSetup *page_setup;
-
-  if (dialog->internal_page_setup_change)
-    return;
-
-  orientation = (GtkPageOrientation) gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->orientation_combo));
-
-  if (dialog->page_setup)
-    {
-      page_setup = gtk_page_setup_copy (dialog->page_setup);
-      if (page_setup)
-        gtk_page_setup_set_orientation (page_setup, orientation);
-
-      gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
-    }
-
-  redraw_page_layout_preview (dialog);
-}
-
-static void
-paper_size_changed (GtkDropDown *combo_box,
-                    GParamSpec *pspec,
-                    GtkPrintUnixDialog *dialog)
-{
-  GtkPageSetup *page_setup, *last_page_setup;
-  GtkPageOrientation orientation;
-  guint selected;
-
-  if (dialog->internal_page_setup_change)
-    return;
-
-  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
-  if (selected != GTK_INVALID_LIST_POSITION)
-    {
-      GListModel *papers, *model;
-
-      papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
-      page_setup = g_list_model_get_item (papers, selected);
-      model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
-
-      if (model == G_LIST_MODEL (dialog->manage_papers_list))
-        {
-          GtkWidget *custom_paper_dialog;
-
-          /* Change from "manage" menu item to last value */
-          if (dialog->page_setup)
-            last_page_setup = g_object_ref (dialog->page_setup);
-          else
-            last_page_setup = gtk_page_setup_new (); /* "good" default */
-
-          if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
-            set_paper_size (dialog, last_page_setup, TRUE, TRUE);
-          g_object_unref (last_page_setup);
-
-          /* And show the custom paper dialog */
-          custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
-          g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
-          gtk_window_present (GTK_WINDOW (custom_paper_dialog));
-
-          g_object_unref (page_setup);
-
-          return;
-        }
-
-      if (dialog->page_setup)
-        orientation = gtk_page_setup_get_orientation (dialog->page_setup);
-      else
-        orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
-
-      gtk_page_setup_set_orientation (page_setup, orientation);
-      gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
-
-      g_object_unref (page_setup);
-    }
-
-  redraw_page_layout_preview (dialog);
-}
-
-/**
- * gtk_print_unix_dialog_new:
- * @title: (nullable): Title of the dialog
- * @parent: (nullable): Transient parent of the dialog
- *
- * Creates a new `GtkPrintUnixDialog`.
- *
- * Returns: a new `GtkPrintUnixDialog`
- */
-GtkWidget *
-gtk_print_unix_dialog_new (const char *title,
-                           GtkWindow   *parent)
-{
-  GtkWidget *result;
-
-  result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
-                         "transient-for", parent,
-                         "title", title ? title : _("Print"),
-                         NULL);
-
-  return result;
-}
-
-/**
- * gtk_print_unix_dialog_get_selected_printer: (attributes org.gtk.Method.get_property=selected-printer)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the currently selected printer.
- *
- * Returns: (transfer none) (nullable): the currently selected printer
- */
-GtkPrinter *
-gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
-  return dialog->current_printer;
-}
-
-/**
- * gtk_print_unix_dialog_set_page_setup: (attributes org.gtk.Method.set_property=page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- * @page_setup: a `GtkPageSetup`
- *
- * Sets the page setup of the `GtkPrintUnixDialog`.
- */
-void
-gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
-                                      GtkPageSetup       *page_setup)
-{
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-  g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
-
-  if (dialog->page_setup != page_setup)
-    {
-      g_clear_object (&dialog->page_setup);
-      dialog->page_setup = g_object_ref (page_setup);
-
-      dialog->page_setup_set = TRUE;
-
-      g_object_notify (G_OBJECT (dialog), "page-setup");
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_page_setup: (attributes org.gtk.Method.get_property=page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the page setup that is used by the `GtkPrintUnixDialog`.
- *
- * Returns: (transfer none): the page setup of @dialog.
- */
-GtkPageSetup *
-gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
-  return dialog->page_setup;
-}
-
-/**
- * gtk_print_unix_dialog_get_page_setup_set:
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether a page setup was set by the user.
- *
- * Returns: whether a page setup was set by user.
- */
-gboolean
-gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
-  return dialog->page_setup_set;
-}
-
-/**
- * gtk_print_unix_dialog_set_current_page: (attributes org.gtk.Method.set_property=current-page)
- * @dialog: a `GtkPrintUnixDialog`
- * @current_page: the current page number.
- *
- * Sets the current page number.
- *
- * If @current_page is not -1, this enables the current page choice
- * for the range of pages to print.
- */
-void
-gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
-                                        int                 current_page)
-{
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
-  if (dialog->current_page != current_page)
-    {
-      dialog->current_page = current_page;
-
-      if (dialog->current_page_radio)
-        gtk_widget_set_sensitive (dialog->current_page_radio, current_page != -1);
-
-      g_object_notify (G_OBJECT (dialog), "current-page");
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_current_page: (attributes org.gtk.Method.get_property=current-page)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the current page of the `GtkPrintUnixDialog`.
- *
- * Returns: the current page of @dialog
- */
-int
-gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
-
-  return dialog->current_page;
-}
-
-static gboolean
-set_active_printer (GtkPrintUnixDialog *dialog,
-                    const char         *printer_name)
-{
-  GListModel *model;
-  GtkPrinter *printer;
-  guint i;
-
-  model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
-
-  for (i = 0; i < g_list_model_get_n_items (model); i++)
-    {
-      printer = g_list_model_get_item (model, i);
-
-      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
-        {
-          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
-
-          g_free (dialog->waiting_for_printer);
-          dialog->waiting_for_printer = NULL;
-
-          g_object_unref (printer);
-          return TRUE;
-        }
-
-      g_object_unref (printer);
-    }
-
-  return FALSE;
-}
-
-/**
- * gtk_print_unix_dialog_set_settings: (attributes org.gtk.Method.set_property=print-settings)
- * @dialog: a `GtkPrintUnixDialog`
- * @settings: (nullable): a `GtkPrintSettings`
- *
- * Sets the `GtkPrintSettings` for the `GtkPrintUnixDialog`.
- *
- * Typically, this is used to restore saved print settings
- * from a previous print operation before the print dialog
- * is shown.
- */
-void
-gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
-                                    GtkPrintSettings   *settings)
-{
-  const char *printer;
-  GtkPageRange *ranges;
-  int num_ranges;
-
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-  g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
-
-  if (settings != NULL)
-    {
-      dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
-      dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
-      dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
-      dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
-      dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
-      dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
-      ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
-      if (ranges)
-        {
-          dialog_set_page_ranges (dialog, ranges, num_ranges);
-          g_free (ranges);
-        }
-
-      dialog->format_for_printer =
-        g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
-    }
-
-  if (dialog->initial_settings)
-    g_object_unref (dialog->initial_settings);
-
-  dialog->initial_settings = settings;
-
-  g_free (dialog->waiting_for_printer);
-  dialog->waiting_for_printer = NULL;
-
-  if (settings)
-    {
-      g_object_ref (settings);
-
-      printer = gtk_print_settings_get_printer (settings);
-
-      if (printer && !set_active_printer (dialog, printer))
-        dialog->waiting_for_printer = g_strdup (printer);
-    }
-
-  g_object_notify (G_OBJECT (dialog), "print-settings");
-}
-
-/**
- * gtk_print_unix_dialog_get_settings: (attributes org.gtk.Method.set_property=print-settings)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets a new `GtkPrintSettings` object that represents the
- * current values in the print dialog.
- *
- * Note that this creates a new object, and you need to unref
- * it if don’t want to keep it.
- *
- * Returns: (transfer full): a new `GtkPrintSettings` object with the values from @dialog
- */
-GtkPrintSettings *
-gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
-{
-  GtkPrintSettings *settings;
-  GtkPrintPages print_pages;
-  GtkPageRange *ranges;
-  int n_ranges;
-
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
-
-  settings = gtk_print_settings_new ();
-
-  if (dialog->current_printer)
-    gtk_print_settings_set_printer (settings,
-                                    gtk_printer_get_name (dialog->current_printer));
-  else
-    gtk_print_settings_set_printer (settings, "default");
-
-  gtk_print_settings_set (settings, "format-for-printer",
-                          dialog->format_for_printer);
-
-  gtk_print_settings_set_collate (settings,
-                                  dialog_get_collate (dialog));
-
-  gtk_print_settings_set_reverse (settings,
-                                  dialog_get_reverse (dialog));
-
-  gtk_print_settings_set_n_copies (settings,
-                                   dialog_get_n_copies (dialog));
-
-  gtk_print_settings_set_scale (settings,
-                                dialog_get_scale (dialog));
-
-  gtk_print_settings_set_page_set (settings,
-                                   dialog_get_page_set (dialog));
-
-  print_pages = dialog_get_print_pages (dialog);
-  gtk_print_settings_set_print_pages (settings, print_pages);
-
-  ranges = dialog_get_page_ranges (dialog, &n_ranges);
-  if (ranges)
-    {
-      gtk_print_settings_set_page_ranges (settings, ranges, n_ranges);
-      g_free (ranges);
-    }
-
-  /* TODO: print when. How to handle? */
-
-  if (dialog->current_printer)
-    _gtk_printer_get_settings_from_options (dialog->current_printer,
-                                            dialog->options,
-                                            settings);
-
-  return settings;
-}
-
-/**
- * gtk_print_unix_dialog_add_custom_tab:
- * @dialog: a `GtkPrintUnixDialog`
- * @child: the widget to put in the custom tab
- * @tab_label: the widget to use as tab label
- *
- * Adds a custom tab to the print dialog.
- */
-void
-gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
-                                      GtkWidget          *child,
-                                      GtkWidget          *tab_label)
-{
-  gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->notebook),
-                            child, tab_label, 2);
-  gtk_widget_set_visible (child, TRUE);
-  gtk_widget_set_visible (tab_label, TRUE);
-}
-
-/**
- * gtk_print_unix_dialog_set_manual_capabilities: (attributes org.gtk.Method.set_property=manual-capabilities)
- * @dialog: a `GtkPrintUnixDialog`
- * @capabilities: the printing capabilities of your application
- *
- * This lets you specify the printing capabilities your application
- * supports.
- *
- * For instance, if you can handle scaling the output then you pass
- * %GTK_PRINT_CAPABILITY_SCALE. If you don’t pass that, then the dialog
- * will only let you select the scale if the printing system automatically
- * handles scaling.
- */
-void
-gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog   *dialog,
-                                               GtkPrintCapabilities  capabilities)
-{
-  if (dialog->manual_capabilities != capabilities)
-    {
-      dialog->manual_capabilities = capabilities;
-      update_dialog_from_capabilities (dialog);
-
-      if (dialog->current_printer)
-        {
-          g_clear_object (&dialog->current_printer);
-          selected_printer_changed (dialog);
-       }
-
-      g_object_notify (G_OBJECT (dialog), "manual-capabilities");
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_manual_capabilities: (attributes org.gtk.Method.get_property=manual-capabilities)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets the capabilities that have been set on this `GtkPrintUnixDialog`.
- *
- * Returns: the printing capabilities
- */
-GtkPrintCapabilities
-gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
-  return dialog->manual_capabilities;
-}
-
-/**
- * gtk_print_unix_dialog_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
- * @dialog: a `GtkPrintUnixDialog`
- * @support_selection: %TRUE to allow print selection
- *
- * Sets whether the print dialog allows user to print a selection.
- */
-void
-gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
-                                             gboolean            support_selection)
-{
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
-  support_selection = support_selection != FALSE;
-  if (dialog->support_selection != support_selection)
-    {
-      dialog->support_selection = support_selection;
-
-      if (dialog->selection_radio)
-        {
-          gtk_widget_set_visible (dialog->selection_radio, support_selection);
-          gtk_widget_set_sensitive (dialog->selection_radio, support_selection && dialog->has_selection);
-        }
-
-      g_object_notify (G_OBJECT (dialog), "support-selection");
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether the print dialog allows user to print a selection.
- *
- * Returns: whether the application supports print of selection
- */
-gboolean
-gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
-  return dialog->support_selection;
-}
-
-/**
- * gtk_print_unix_dialog_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
- * @dialog: a `GtkPrintUnixDialog`
- * @has_selection: %TRUE indicates that a selection exists
- *
- * Sets whether a selection exists.
- */
-void
-gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
-                                         gboolean            has_selection)
-{
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
-  has_selection = has_selection != FALSE;
-  if (dialog->has_selection != has_selection)
-    {
-      dialog->has_selection = has_selection;
-
-      if (dialog->selection_radio)
-        {
-          if (dialog->support_selection)
-            gtk_widget_set_sensitive (dialog->selection_radio, has_selection);
-          else
-            gtk_widget_set_sensitive (dialog->selection_radio, FALSE);
-        }
-
-      g_object_notify (G_OBJECT (dialog), "has-selection");
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether there is a selection.
- *
- * Returns: whether there is a selection
- */
-gboolean
-gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
-  return dialog->has_selection;
-}
-
-/**
- * gtk_print_unix_dialog_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- * @embed: embed page setup selection
- *
- * Embed page size combo box and orientation combo box into page setup page.
- */
-void
-gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
-                                            gboolean            embed)
-{
-  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
-
-  embed = embed != FALSE;
-  if (dialog->embed_page_setup != embed)
-    {
-      dialog->embed_page_setup = embed;
-
-      gtk_widget_set_sensitive (dialog->paper_size_combo, dialog->embed_page_setup);
-      gtk_widget_set_sensitive (dialog->orientation_combo, dialog->embed_page_setup);
-
-      if (dialog->embed_page_setup)
-        {
-          if (dialog->paper_size_combo != NULL)
-            g_signal_connect (dialog->paper_size_combo, "notify::selected", G_CALLBACK (paper_size_changed), dialog);
-
-          if (dialog->orientation_combo)
-            g_signal_connect (dialog->orientation_combo, "notify::selected", G_CALLBACK (orientation_changed), dialog);
-        }
-      else
-        {
-          if (dialog->paper_size_combo != NULL)
-            g_signal_handlers_disconnect_by_func (dialog->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
-
-          if (dialog->orientation_combo)
-            g_signal_handlers_disconnect_by_func (dialog->orientation_combo, G_CALLBACK (orientation_changed), dialog);
-        }
-
-      dialog->internal_page_setup_change = TRUE;
-      update_paper_sizes (dialog);
-      dialog->internal_page_setup_change = FALSE;
-    }
-}
-
-/**
- * gtk_print_unix_dialog_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
- * @dialog: a `GtkPrintUnixDialog`
- *
- * Gets whether to embed the page setup.
- *
- * Returns: whether to embed the page setup
- */
-gboolean
-gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
-
-  return dialog->embed_page_setup;
-}
diff --git a/gtk/gtkprintunixdialog.h b/gtk/gtkprintunixdialog.h
deleted file mode 100644 (file)
index 3c12c7a..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* GtkPrintUnixDialog
- * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtkunixprint.h> can be included directly."
-#endif
-
-#include <gtk/gtk.h>
-#include <gtk/gtkprinter.h>
-#include <gtk/gtkprintjob.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_PRINT_UNIX_DIALOG                  (gtk_print_unix_dialog_get_type ())
-#define GTK_PRINT_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialog))
-#define GTK_IS_PRINT_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_UNIX_DIALOG))
-
-
-typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog;
-
-
-GDK_AVAILABLE_IN_ALL
-GType                gtk_print_unix_dialog_get_type                (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GtkWidget *          gtk_print_unix_dialog_new                     (const char *title,
-                                                                    GtkWindow   *parent);
-
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_page_setup          (GtkPrintUnixDialog *dialog,
-                                                                   GtkPageSetup       *page_setup);
-GDK_AVAILABLE_IN_ALL
-GtkPageSetup *       gtk_print_unix_dialog_get_page_setup          (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_current_page        (GtkPrintUnixDialog *dialog,
-                                                                   int                 current_page);
-GDK_AVAILABLE_IN_ALL
-int                  gtk_print_unix_dialog_get_current_page        (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_settings            (GtkPrintUnixDialog *dialog,
-                                                                   GtkPrintSettings   *settings);
-GDK_AVAILABLE_IN_ALL
-GtkPrintSettings *   gtk_print_unix_dialog_get_settings            (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-GtkPrinter *         gtk_print_unix_dialog_get_selected_printer    (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_add_custom_tab          (GtkPrintUnixDialog *dialog,
-                                                                   GtkWidget          *child,
-                                                                   GtkWidget          *tab_label);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
-                                                                   GtkPrintCapabilities capabilities);
-GDK_AVAILABLE_IN_ALL
-GtkPrintCapabilities gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog  *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_support_selection   (GtkPrintUnixDialog  *dialog,
-                                                                   gboolean             support_selection);
-GDK_AVAILABLE_IN_ALL
-gboolean             gtk_print_unix_dialog_get_support_selection   (GtkPrintUnixDialog  *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_has_selection       (GtkPrintUnixDialog  *dialog,
-                                                                   gboolean             has_selection);
-GDK_AVAILABLE_IN_ALL
-gboolean             gtk_print_unix_dialog_get_has_selection       (GtkPrintUnixDialog  *dialog);
-GDK_AVAILABLE_IN_ALL
-void                 gtk_print_unix_dialog_set_embed_page_setup    (GtkPrintUnixDialog *dialog,
-                                                                   gboolean            embed);
-GDK_AVAILABLE_IN_ALL
-gboolean             gtk_print_unix_dialog_get_embed_page_setup    (GtkPrintUnixDialog *dialog);
-GDK_AVAILABLE_IN_ALL
-gboolean             gtk_print_unix_dialog_get_page_setup_set      (GtkPrintUnixDialog *dialog);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintUnixDialog, g_object_unref)
-
-G_END_DECLS
-
diff --git a/gtk/gtkprintutilsprivate.h b/gtk/gtkprintutilsprivate.h
deleted file mode 100644 (file)
index 9e63e91..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <gdk/gdk.h>
-#include "gtkenums.h"
-
-
-G_BEGIN_DECLS
-
-#define MM_PER_INCH 25.4
-#define POINTS_PER_INCH 72
-
-double _gtk_print_convert_to_mm   (double len, GtkUnit unit);
-double _gtk_print_convert_from_mm (double len, GtkUnit unit);
-
-G_END_DECLS
-
diff --git a/gtk/gtkunixprint.h b/gtk/gtkunixprint.h
deleted file mode 100644 (file)
index c285b4e..0000000
+++ /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 <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#define __GTK_UNIX_PRINT_H_INSIDE__
-
-#include <gtk/gtkpagesetupunixdialog.h>
-#include <gtk/gtkprinter.h>
-#include <gtk/gtkprintjob.h>
-#include <gtk/gtkprintunixdialog.h>
-
-#undef __GTK_UNIX_PRINT_H_INSIDE__
-
index 479a7b6269d6e6f244bae161960e3625abe3a1ee..7b8926451b0bdd194bddeaf7a0b3af628efcf29d 100644 (file)
@@ -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 (file)
index e5c9d0b..0000000
+++ /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 (file)
index d4f79e2..0000000
+++ /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 (file)
index 0000000..375927e
--- /dev/null
@@ -0,0 +1,1008 @@
+/* GtkCustomPaperUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007, 2008 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "config.h"
+#include <string.h>
+#include <locale.h>
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+#include <langinfo.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+
+#include "deprecated/gtkliststore.h"
+
+#include "gtksignallistitemfactory.h"
+#include "gtklabel.h"
+#include "gtkspinbutton.h"
+
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprintutilsprivate.h"
+#include "deprecated/gtkdialogprivate.h"
+
+#define LEGACY_CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
+#define CUSTOM_PAPER_FILENAME "custom-papers"
+
+
+typedef struct
+{
+  GtkUnit    display_unit;
+  GtkWidget *spin_button;
+} UnitWidget;
+
+struct _GtkCustomPaperUnixDialog
+{
+  GtkDialog parent_instance;
+
+  GtkWidget *listview;
+  GtkWidget *values_box;
+  GtkWidget *printer_combo;
+  GtkWidget *width_widget;
+  GtkWidget *height_widget;
+  GtkWidget *top_widget;
+  GtkWidget *bottom_widget;
+  GtkWidget *left_widget;
+  GtkWidget *right_widget;
+
+  gulong printer_inserted_tag;
+
+  guint request_details_tag;
+  GtkPrinter *request_details_printer;
+
+  guint non_user_change : 1;
+
+  GListStore *custom_paper_list;
+  GListModel *printer_list;
+
+  GList *print_backends;
+};
+
+typedef struct _GtkCustomPaperUnixDialogClass GtkCustomPaperUnixDialogClass;
+
+struct _GtkCustomPaperUnixDialogClass
+{
+  GtkDialogClass parent_class;
+};
+
+
+enum {
+  PRINTER_LIST_COL_NAME,
+  PRINTER_LIST_COL_PRINTER,
+  PRINTER_LIST_N_COLS
+};
+
+
+G_DEFINE_TYPE (GtkCustomPaperUnixDialog, gtk_custom_paper_unix_dialog, GTK_TYPE_DIALOG)
+
+
+static void gtk_custom_paper_unix_dialog_constructed (GObject *object);
+static void gtk_custom_paper_unix_dialog_finalize  (GObject                *object);
+static void populate_dialog                        (GtkCustomPaperUnixDialog *dialog);
+
+
+
+GtkUnit
+_gtk_print_get_default_user_units (void)
+{
+  /* Translate to the default units to use for presenting
+   * lengths to the user. Translate to default:inch if you
+   * want inches, otherwise translate to default:mm.
+   * Do *not* translate it to "predefinito:mm", if it
+   * it isn't default:mm or default:inch it will not work
+   */
+  char *e = _("default:mm");
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+  char *imperial = NULL;
+
+  imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
+  if (imperial && imperial[0] == 2 )
+    return GTK_UNIT_INCH;  /* imperial */
+  if (imperial && imperial[0] == 1 )
+    return GTK_UNIT_MM;  /* metric */
+#endif
+
+  if (strcmp (e, "default:inch")==0)
+    return GTK_UNIT_INCH;
+  else if (strcmp (e, "default:mm"))
+    g_warning ("Whoever translated default:mm did so wrongly.");
+  return GTK_UNIT_MM;
+}
+
+static char *
+custom_paper_get_legacy_filename (void)
+{
+  char *filename;
+
+  filename = g_build_filename (g_get_home_dir (),
+                               LEGACY_CUSTOM_PAPER_FILENAME, NULL);
+  g_assert (filename != NULL);
+  return filename;
+}
+
+static char *
+custom_paper_get_filename (void)
+{
+  char *filename;
+
+  filename = g_build_filename (g_get_user_config_dir (),
+                               "gtk-4.0",
+                               CUSTOM_PAPER_FILENAME, NULL);
+  g_assert (filename != NULL);
+  return filename;
+}
+
+GList *
+_gtk_load_custom_papers (void)
+{
+  GKeyFile *keyfile;
+  char *filename;
+  char **groups;
+  gsize n_groups, i;
+  gboolean load_ok;
+  GList *result = NULL;
+
+  filename = custom_paper_get_filename ();
+
+  keyfile = g_key_file_new ();
+  load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
+  g_free (filename);
+  if (!load_ok)
+    {
+      /* try legacy file */
+      filename = custom_paper_get_legacy_filename ();
+      load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
+      g_free (filename);
+    }
+  if (!load_ok)
+    {
+      g_key_file_free (keyfile);
+      return NULL;
+    }
+
+  groups = g_key_file_get_groups (keyfile, &n_groups);
+  for (i = 0; i < n_groups; ++i)
+    {
+      GtkPageSetup *page_setup;
+
+      page_setup = gtk_page_setup_new_from_key_file (keyfile, groups[i], NULL);
+      if (!page_setup)
+        continue;
+
+      result = g_list_prepend (result, page_setup);
+    }
+
+  g_strfreev (groups);
+  g_key_file_free (keyfile);
+
+  return g_list_reverse (result);
+}
+
+void
+gtk_print_load_custom_papers (GListStore *store)
+{
+  GList *papers, *p;
+  GtkPageSetup *page_setup;
+
+  g_list_store_remove_all (store);
+
+  papers = _gtk_load_custom_papers ();
+  for (p = papers; p; p = p->next)
+    {
+      page_setup = p->data;
+      g_list_store_append (store, page_setup);
+      g_object_unref (page_setup);
+    }
+
+  g_list_free (papers);
+}
+
+static void
+gtk_print_save_custom_papers (GListStore *store)
+{
+  GKeyFile *keyfile;
+  char *filename, *data, *parentdir;
+  gsize len;
+  int i = 0;
+
+  keyfile = g_key_file_new ();
+
+  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
+    {
+      GtkPageSetup *page_setup;
+      char group[32];
+
+      page_setup = g_list_model_get_item (G_LIST_MODEL (store), i);
+      g_snprintf (group, sizeof (group), "Paper%u", i);
+      gtk_page_setup_to_key_file (page_setup, keyfile, group);
+      g_object_unref (page_setup);
+    }
+
+  filename = custom_paper_get_filename ();
+  parentdir = g_build_filename (g_get_user_config_dir (),
+                                "gtk-4.0",
+                                NULL);
+  if (g_mkdir_with_parents (parentdir, 0700) == 0)
+    {
+      data = g_key_file_to_data (keyfile, &len, NULL);
+      g_file_set_contents (filename, data, len, NULL);
+      g_free (data);
+    }
+  g_free (parentdir);
+  g_free (filename);
+}
+
+static void
+gtk_custom_paper_unix_dialog_class_init (GtkCustomPaperUnixDialogClass *class)
+{
+  G_OBJECT_CLASS (class)->constructed = gtk_custom_paper_unix_dialog_constructed;
+  G_OBJECT_CLASS (class)->finalize = gtk_custom_paper_unix_dialog_finalize;
+}
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *dialog,
+                                 int        response,
+                                 gpointer   user_data)
+{
+  GtkCustomPaperUnixDialog *self = GTK_CUSTOM_PAPER_UNIX_DIALOG (dialog);
+
+  gtk_print_save_custom_papers (self->custom_paper_list);
+}
+
+static gboolean
+match_func (gpointer item, gpointer user_data)
+{
+  return !gtk_printer_is_virtual (GTK_PRINTER (item));
+}
+
+static void
+gtk_custom_paper_unix_dialog_init (GtkCustomPaperUnixDialog *dialog)
+{
+  GtkPrinter *printer;
+  GListStore *printer_list;
+  GListStore *printer_list_list;
+  GListModel *full_list;
+  GtkFilter *filter;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+  dialog->print_backends = NULL;
+
+  dialog->request_details_printer = NULL;
+  dialog->request_details_tag = 0;
+
+  printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
+  printer_list = g_list_store_new (GTK_TYPE_PRINTER);
+  printer = gtk_printer_new (_("Margins from Printer…"), NULL, FALSE);
+  g_list_store_append (printer_list, printer);
+  g_object_unref (printer);
+  g_list_store_append (printer_list_list, printer_list);
+  g_object_unref (printer_list);
+
+  full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
+
+  filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
+  dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
+
+  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+
+  populate_dialog (dialog);
+
+  g_signal_connect (dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), NULL);
+}
+
+static void
+gtk_custom_paper_unix_dialog_constructed (GObject *object)
+{
+  gboolean use_header;
+
+  G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->constructed (object);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  g_object_get (object, "use-header-bar", &use_header, NULL);
+  if (!use_header)
+    {
+      gtk_dialog_add_buttons (GTK_DIALOG (object),
+                              _("_Close"), GTK_RESPONSE_CLOSE,
+                              NULL);
+      gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_CLOSE);
+    }
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+static void
+gtk_custom_paper_unix_dialog_finalize (GObject *object)
+{
+  GtkCustomPaperUnixDialog *dialog = GTK_CUSTOM_PAPER_UNIX_DIALOG (object);
+  GList *node;
+
+  if (dialog->printer_list)
+    {
+      g_signal_handler_disconnect (dialog->printer_list, dialog->printer_inserted_tag);
+      g_object_unref (dialog->printer_list);
+      dialog->printer_list = NULL;
+    }
+
+  if (dialog->request_details_tag)
+    {
+      g_signal_handler_disconnect (dialog->request_details_printer,
+                                   dialog->request_details_tag);
+      g_object_unref (dialog->request_details_printer);
+      dialog->request_details_printer = NULL;
+      dialog->request_details_tag = 0;
+    }
+
+  g_clear_object (&dialog->custom_paper_list);
+
+  for (node = dialog->print_backends; node; node = node->next)
+    gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
+  g_list_free_full (dialog->print_backends, g_object_unref);
+  dialog->print_backends = NULL;
+
+  G_OBJECT_CLASS (gtk_custom_paper_unix_dialog_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_custom_paper_unix_dialog_new:
+ * @title: (nullable): the title of the dialog
+ * @parent: (nullable): transient parent of the dialog
+ *
+ * Creates a new custom paper dialog.
+ *
+ * Returns: the new `GtkCustomPaperUnixDialog`
+ */
+GtkWidget *
+_gtk_custom_paper_unix_dialog_new (GtkWindow   *parent,
+                                   const char *title)
+{
+  GtkWidget *result;
+
+  if (title == NULL)
+    title = _("Manage Custom Sizes");
+
+  result = g_object_new (GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG,
+                         "title", title,
+                         "transient-for", parent,
+                         "modal", parent != NULL,
+                         "destroy-with-parent", TRUE,
+                         "resizable", FALSE,
+                         NULL);
+
+  return result;
+}
+
+static void
+load_print_backends (GtkCustomPaperUnixDialog *dialog)
+{
+  GListModel *full_list;
+  GListStore *printer_list_list;
+  GList *node;
+
+  full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
+  printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
+
+  if (g_module_supported ())
+    dialog->print_backends = gtk_print_backend_load_modules ();
+
+  for (node = dialog->print_backends; node != NULL; node = node->next)
+    {
+      GtkPrintBackend *backend = GTK_PRINT_BACKEND (node->data);
+      g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
+    }
+}
+
+static void unit_widget_changed (GtkCustomPaperUnixDialog *dialog);
+
+static GtkWidget *
+new_unit_widget (GtkCustomPaperUnixDialog *dialog,
+                 GtkUnit                   unit,
+                 GtkWidget                *mnemonic_label)
+{
+  GtkWidget *hbox, *button, *label;
+  UnitWidget *data;
+
+  data = g_new0 (UnitWidget, 1);
+  data->display_unit = unit;
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+  button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
+  gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
+  if (unit == GTK_UNIT_INCH)
+    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
+  else
+    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
+
+  gtk_box_append (GTK_BOX (hbox), button);
+
+  data->spin_button = button;
+
+  g_signal_connect_swapped (button, "value-changed",
+                            G_CALLBACK (unit_widget_changed), dialog);
+
+  if (unit == GTK_UNIT_INCH)
+    label = gtk_label_new (_("inch"));
+  else
+    label = gtk_label_new (_("mm"));
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+
+  gtk_box_append (GTK_BOX (hbox), label);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (mnemonic_label), button);
+
+  g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
+
+  return hbox;
+}
+
+static double
+unit_widget_get (GtkWidget *unit_widget)
+{
+  UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
+  return _gtk_print_convert_to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
+                                   data->display_unit);
+}
+
+static void
+unit_widget_set (GtkWidget *unit_widget,
+                 double     value)
+{
+  UnitWidget *data;
+
+  data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
+                             _gtk_print_convert_from_mm (value, data->display_unit));
+}
+
+static void
+update_combo_sensitivity_from_printers (GtkCustomPaperUnixDialog *dialog)
+{
+  gboolean sensitive = FALSE;
+
+  if (g_list_model_get_n_items (dialog->printer_list) > 1)
+    sensitive = TRUE;
+
+  gtk_widget_set_sensitive (dialog->printer_combo, sensitive);
+}
+
+static void
+update_custom_widgets_from_list (GtkCustomPaperUnixDialog *dialog)
+{
+  GListModel *model;
+  GtkPageSetup *page_setup;
+
+  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+  page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+  dialog->non_user_change = TRUE;
+  if (page_setup != NULL)
+    {
+      unit_widget_set (dialog->width_widget,
+                       gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
+      unit_widget_set (dialog->height_widget,
+                       gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
+      unit_widget_set (dialog->top_widget,
+                       gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
+      unit_widget_set (dialog->bottom_widget,
+                       gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
+      unit_widget_set (dialog->left_widget,
+                       gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
+      unit_widget_set (dialog->right_widget,
+                       gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
+
+      gtk_widget_set_sensitive (dialog->values_box, TRUE);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (dialog->values_box, FALSE);
+    }
+
+  if (dialog->printer_list)
+    update_combo_sensitivity_from_printers (dialog);
+  dialog->non_user_change = FALSE;
+}
+
+static void
+selected_custom_paper_changed (GObject                  *list,
+                               GParamSpec               *pspec,
+                               GtkCustomPaperUnixDialog *dialog)
+{
+  update_custom_widgets_from_list (dialog);
+}
+
+static void
+unit_widget_changed (GtkCustomPaperUnixDialog *dialog)
+{
+  double w, h, top, bottom, left, right;
+  GListModel *model;
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+
+  if (dialog->non_user_change)
+    return;
+
+  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+  page_setup = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+  if (page_setup != NULL)
+    {
+      w = unit_widget_get (dialog->width_widget);
+      h = unit_widget_get (dialog->height_widget);
+
+      paper_size = gtk_page_setup_get_paper_size (page_setup);
+      gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
+
+      top = unit_widget_get (dialog->top_widget);
+      bottom = unit_widget_get (dialog->bottom_widget);
+      left = unit_widget_get (dialog->left_widget);
+      right = unit_widget_get (dialog->right_widget);
+
+      gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
+      gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
+      gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
+      gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
+    }
+}
+
+static gboolean
+custom_paper_name_used (GtkCustomPaperUnixDialog *dialog,
+                        const char               *name)
+{
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+  guint i;
+
+  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)); i++)
+    {
+      page_setup = g_list_model_get_item (G_LIST_MODEL (dialog->custom_paper_list), i);
+      paper_size = gtk_page_setup_get_paper_size (page_setup);
+      if (strcmp (name, gtk_paper_size_get_name (paper_size)) == 0)
+        {
+          g_object_unref (page_setup);
+          return TRUE;
+        }
+      g_object_unref (page_setup);
+    }
+
+  return FALSE;
+}
+
+static void
+add_custom_paper (GtkCustomPaperUnixDialog *dialog)
+{
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+  char *name;
+  int i;
+
+  i = 1;
+  name = NULL;
+  do
+    {
+      g_free (name);
+      name = g_strdup_printf (_("Custom Size %d"), i);
+      i++;
+    } while (custom_paper_name_used (dialog, name));
+
+  page_setup = gtk_page_setup_new ();
+  paper_size = gtk_paper_size_new_custom (name, name,
+                                          gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
+                                          gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
+                                          GTK_UNIT_MM);
+  gtk_page_setup_set_paper_size (page_setup, paper_size);
+  gtk_paper_size_free (paper_size);
+
+  g_list_store_append (dialog->custom_paper_list, page_setup);
+  g_object_unref (page_setup);
+
+  /* FIXME start editing */
+
+  g_free (name);
+}
+
+static void
+remove_custom_paper (GtkCustomPaperUnixDialog *dialog)
+{
+  GListModel *model;
+  guint selected;
+
+  model = G_LIST_MODEL (gtk_list_view_get_model (GTK_LIST_VIEW (dialog->listview)));
+  selected = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model));
+  if (selected != GTK_INVALID_LIST_POSITION)
+    g_list_store_remove (dialog->custom_paper_list, selected);
+}
+
+static void
+set_margins_from_printer (GtkCustomPaperUnixDialog *dialog,
+                          GtkPrinter               *printer)
+{
+  double top, bottom, left, right;
+
+  top = bottom = left = right = 0;
+  if (!gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right))
+    return;
+
+  dialog->non_user_change = TRUE;
+  unit_widget_set (dialog->top_widget, _gtk_print_convert_to_mm (top, GTK_UNIT_POINTS));
+  unit_widget_set (dialog->bottom_widget, _gtk_print_convert_to_mm (bottom, GTK_UNIT_POINTS));
+  unit_widget_set (dialog->left_widget, _gtk_print_convert_to_mm (left, GTK_UNIT_POINTS));
+  unit_widget_set (dialog->right_widget, _gtk_print_convert_to_mm (right, GTK_UNIT_POINTS));
+  dialog->non_user_change = FALSE;
+
+  /* Only send one change */
+  unit_widget_changed (dialog);
+}
+
+static void
+get_margins_finished_callback (GtkPrinter               *printer,
+                               gboolean                  success,
+                               GtkCustomPaperUnixDialog *dialog)
+{
+  g_signal_handler_disconnect (dialog->request_details_printer,
+                               dialog->request_details_tag);
+  g_object_unref (dialog->request_details_printer);
+  dialog->request_details_tag = 0;
+  dialog->request_details_printer = NULL;
+
+  if (success)
+    set_margins_from_printer (dialog, printer);
+
+  gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
+}
+
+static void
+margins_from_printer_changed (GtkCustomPaperUnixDialog *dialog)
+{
+  guint selected;
+  GtkPrinter *printer;
+
+  if (dialog->request_details_tag)
+    {
+      g_signal_handler_disconnect (dialog->request_details_printer,
+                                   dialog->request_details_tag);
+      g_object_unref (dialog->request_details_printer);
+      dialog->request_details_printer = NULL;
+      dialog->request_details_tag = 0;
+    }
+
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
+  if (selected != 0)
+    {
+      GListModel *model;
+
+      model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
+      printer = g_list_model_get_item (model, selected);
+
+      if (printer)
+        {
+          if (gtk_printer_has_details (printer))
+            {
+              set_margins_from_printer (dialog, printer);
+              gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), 0);
+            }
+          else
+            {
+              dialog->request_details_printer = g_object_ref (printer);
+              dialog->request_details_tag =
+                g_signal_connect (printer, "details-acquired",
+                                  G_CALLBACK (get_margins_finished_callback), dialog);
+              gtk_printer_request_details (printer);
+            }
+
+          g_object_unref (printer);
+        }
+    }
+}
+
+static GtkWidget *
+wrap_in_frame (const char *label,
+               GtkWidget   *child)
+{
+  GtkWidget *frame, *label_widget;
+  char *bold_text;
+
+  label_widget = gtk_label_new (NULL);
+  gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
+  gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
+
+  bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
+  gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
+  g_free (bold_text);
+
+  frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_append (GTK_BOX (frame), label_widget);
+
+  gtk_widget_set_margin_start (child, 12);
+  gtk_widget_set_halign (child, GTK_ALIGN_FILL);
+  gtk_widget_set_valign (child, GTK_ALIGN_FILL);
+
+  gtk_box_append (GTK_BOX (frame), child);
+
+  return frame;
+}
+
+static void
+setup_item (GtkSignalListItemFactory *factory,
+            GtkListItem              *item)
+{
+  gtk_list_item_set_child (item, gtk_editable_label_new (""));
+}
+
+static void
+label_changed (GObject     *object,
+               GParamSpec  *pspec,
+               GtkListItem *item)
+{
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+  const char *new_text;
+
+  page_setup = gtk_list_item_get_item (item);
+
+  new_text = gtk_editable_get_text (GTK_EDITABLE (object));
+
+  paper_size = gtk_paper_size_new_custom (new_text, new_text,
+                                          gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
+                                          gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM), GTK_UNIT_MM);
+  gtk_page_setup_set_paper_size (page_setup, paper_size);
+  gtk_paper_size_free (paper_size);
+}
+
+static void
+state_changed (GtkWidget     *item,
+               GtkStateFlags  old_state,
+               GtkWidget     *label)
+{
+  gboolean selected;
+
+  selected = (gtk_widget_get_state_flags (item) & GTK_STATE_FLAG_SELECTED) != 0;
+  gtk_editable_set_editable (GTK_EDITABLE (label), selected);
+}
+
+static void
+bind_item (GtkSignalListItemFactory *factory,
+           GtkListItem              *item)
+{
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+  GtkWidget *label;
+
+  page_setup = gtk_list_item_get_item (item);
+  label = gtk_list_item_get_child (item);
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+  gtk_editable_set_text (GTK_EDITABLE (label),
+                         gtk_paper_size_get_display_name (paper_size));
+  g_signal_connect (label, "notify::text",
+                    G_CALLBACK (label_changed), item);
+  g_signal_connect (gtk_widget_get_parent (label), "state-flags-changed",
+                    G_CALLBACK (state_changed), label);
+}
+
+static void
+unbind_item (GtkSignalListItemFactory *factory,
+             GtkListItem              *item)
+{
+  GtkWidget *label;
+
+  label = gtk_list_item_get_child (item);
+  g_signal_handlers_disconnect_by_func (label, label_changed, item);
+  g_signal_handlers_disconnect_by_func (gtk_widget_get_parent (label), state_changed, label);
+}
+
+static void
+setup_printer_item (GtkSignalListItemFactory *factory,
+                    GtkListItem              *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new ("");
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_printer_item (GtkSignalListItemFactory *factory,
+                   GtkListItem              *item)
+{
+  GtkPrinter *printer;
+  GtkWidget *label;
+
+  printer = gtk_list_item_get_item (item);
+  label = gtk_list_item_get_child (item);
+
+  gtk_label_set_label (GTK_LABEL (label), gtk_printer_get_name (printer));
+}
+
+static void
+populate_dialog (GtkCustomPaperUnixDialog *dialog)
+{
+  GtkDialog *cpu_dialog = GTK_DIALOG (dialog);
+  GtkWidget *content_area;
+  GtkWidget *grid, *label, *widget, *frame, *combo;
+  GtkWidget *hbox, *vbox, *listview, *scrolled, *toolbar, *button;
+  GtkUnit user_units;
+  GtkSelectionModel *model;
+  GtkListItemFactory *factory;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  content_area = gtk_dialog_get_content_area (cpu_dialog);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+  gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 18);
+  gtk_widget_set_margin_start (hbox, 20);
+  gtk_widget_set_margin_end (hbox, 20);
+  gtk_widget_set_margin_top (hbox, 20);
+  gtk_widget_set_margin_bottom (hbox, 20);
+  gtk_box_append (GTK_BOX (content_area), hbox);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_box_append (GTK_BOX (hbox), vbox);
+
+  scrolled = gtk_scrolled_window_new ();
+  gtk_widget_set_vexpand (scrolled, TRUE);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
+  gtk_box_append (GTK_BOX (vbox), scrolled);
+
+  model = GTK_SELECTION_MODEL (gtk_single_selection_new (g_object_ref (G_LIST_MODEL (dialog->custom_paper_list))));
+  g_signal_connect (model, "notify::selected", G_CALLBACK (selected_custom_paper_changed), dialog);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
+  g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
+
+  listview = gtk_list_view_new (model, factory);
+  gtk_widget_set_size_request (listview, 140, -1);
+
+  dialog->listview = listview;
+
+  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), listview);
+
+  toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+  gtk_widget_add_css_class (toolbar, "linked");
+
+  gtk_box_append (GTK_BOX (vbox), toolbar);
+
+  button = gtk_button_new_from_icon_name ("list-add-symbolic");
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), dialog);
+
+  gtk_box_append (GTK_BOX (toolbar), button);
+
+  button = gtk_button_new_from_icon_name ("list-remove-symbolic");
+  g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), dialog);
+
+  gtk_box_append (GTK_BOX (toolbar), button);
+
+  user_units = _gtk_print_get_default_user_units ();
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
+  dialog->values_box = vbox;
+  gtk_box_append (GTK_BOX (hbox), vbox);
+
+  grid = gtk_grid_new ();
+
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+
+  label = gtk_label_new_with_mnemonic (_("_Width:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->width_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
+
+  label = gtk_label_new_with_mnemonic (_("_Height:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->height_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
+
+  frame = wrap_in_frame (_("Paper Size"), grid);
+  gtk_box_append (GTK_BOX (vbox), frame);
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+
+  label = gtk_label_new_with_mnemonic (_("_Top:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->top_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 0, 1, 1);
+
+  label = gtk_label_new_with_mnemonic (_("_Bottom:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->bottom_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 1, 1, 1);
+
+  label = gtk_label_new_with_mnemonic (_("_Left:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->left_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 2, 1, 1);
+
+  label = gtk_label_new_with_mnemonic (_("_Right:"));
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
+
+  widget = new_unit_widget (dialog, user_units, label);
+  dialog->right_widget = widget;
+  gtk_grid_attach (GTK_GRID (grid), widget, 1, 3, 1, 1);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_grid_attach (GTK_GRID (grid), hbox, 0, 4, 2, 1);
+
+  combo = gtk_drop_down_new (g_object_ref (dialog->printer_list), NULL);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (combo), factory);
+  g_object_unref (factory);
+
+  dialog->printer_combo = combo;
+
+  dialog->printer_inserted_tag =
+    g_signal_connect_swapped (dialog->printer_list, "items-changed",
+                              G_CALLBACK (update_combo_sensitivity_from_printers), dialog);
+  update_combo_sensitivity_from_printers (dialog);
+
+  gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), 0);
+  gtk_box_append (GTK_BOX (hbox), combo);
+
+  g_signal_connect_swapped (combo, "notify::selected",
+                            G_CALLBACK (margins_from_printer_changed), dialog);
+
+  frame = wrap_in_frame (_("Paper Margins"), grid);
+  gtk_box_append (GTK_BOX (vbox), frame);
+
+  update_custom_widgets_from_list (dialog);
+
+  if (g_list_model_get_n_items (G_LIST_MODEL (dialog->custom_paper_list)) == 0)
+    add_custom_paper (dialog);
+
+  load_print_backends (dialog);
+}
diff --git a/gtk/print/gtkcustompaperunixdialog.h b/gtk/print/gtkcustompaperunixdialog.h
new file mode 100644 (file)
index 0000000..630737a
--- /dev/null
@@ -0,0 +1,40 @@
+/* GtkCustomPaperUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG                  (gtk_custom_paper_unix_dialog_get_type ())
+#define GTK_CUSTOM_PAPER_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG, GtkCustomPaperUnixDialog))
+#define GTK_IS_CUSTOM_PAPER_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CUSTOM_PAPER_UNIX_DIALOG))
+
+typedef struct _GtkCustomPaperUnixDialog         GtkCustomPaperUnixDialog;
+
+GDK_AVAILABLE_IN_ALL
+GType             gtk_custom_paper_unix_dialog_get_type           (void) G_GNUC_CONST;
+GtkWidget *       _gtk_custom_paper_unix_dialog_new                (GtkWindow   *parent,
+                                                                    const char *title);
+GtkUnit           _gtk_print_get_default_user_units                (void);
+void               gtk_print_load_custom_papers                    (GListStore *store);
+GList *           _gtk_load_custom_papers                          (void);
+
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkpagesetupunixdialog.c b/gtk/print/gtkpagesetupunixdialog.c
new file mode 100644 (file)
index 0000000..e9f5cfd
--- /dev/null
@@ -0,0 +1,950 @@
+/* GtkPageSetupUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007, 2008 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "config.h"
+#include <string.h>
+#include <locale.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+
+#include "gtkbutton.h"
+#include "gtkscrolledwindow.h"
+#include "gtkcheckbutton.h"
+#include "gtklabel.h"
+#include "gtkgrid.h"
+
+#include "gtkpagesetupunixdialog.h"
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkpapersize.h"
+#include "gtkprintutilsprivate.h"
+#include "deprecated/gtkdialogprivate.h"
+
+/**
+ * GtkPageSetupUnixDialog:
+ *
+ * `GtkPageSetupUnixDialog` implements a page setup dialog for platforms
+ * which don’t provide a native page setup dialog, like Unix.
+ *
+ * ![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 ("<b>%s</b>\n%s", name, location ? location : "");
+  gtk_label_set_markup (GTK_LABEL (label), str);
+  g_free (str);
+}
+
+static void
+gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
+{
+  GtkListItemFactory *factory;
+  GListStore *store;
+  GListModel *paper_size_list;
+  GtkPrinter *printer;
+  GListStore *printer_list;
+  GListStore *printer_list_list;
+  GListModel *full_list;
+  GtkFilter *filter;
+  GtkPageSetup *page_setup;
+
+  dialog->internal_change = TRUE;
+  dialog->print_backends = NULL;
+
+  gtk_widget_init_template (GTK_WIDGET (dialog));
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          _("_Cancel"), GTK_RESPONSE_CANCEL,
+                          _("_Apply"), GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+  dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  page_setup = gtk_page_setup_new ();
+  g_list_store_append (dialog->manage_papers_list, page_setup);
+  g_object_unref (page_setup);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+  g_object_unref (factory);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
+  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+  g_object_unref (factory);
+
+  store = g_list_store_new (G_TYPE_LIST_MODEL);
+  g_list_store_append (store, dialog->page_setup_list);
+  g_list_store_append (store, dialog->custom_paper_list);
+  g_list_store_append (store, dialog->manage_papers_list);
+  paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
+  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
+  g_object_unref (paper_size_list);
+
+  /* Do this in code, we want the translatable strings without the markup */
+  printer_list_list = g_list_store_new (G_TYPE_LIST_MODEL);
+  printer_list = g_list_store_new (GTK_TYPE_PRINTER);
+  printer = gtk_printer_new (_("Any Printer"), NULL, FALSE);
+  gtk_printer_set_location (printer, _("For portable documents"));
+  g_list_store_append (printer_list, printer);
+  g_object_unref (printer);
+  g_list_store_append (printer_list_list, printer_list);
+  g_object_unref (printer_list);
+
+  full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
+
+  filter = GTK_FILTER (gtk_custom_filter_new (match_func, NULL, NULL));
+  dialog->printer_list = G_LIST_MODEL (gtk_filter_list_model_new (full_list, filter));
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_printer_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_printer_item), dialog);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->printer_combo), factory);
+  g_object_unref (factory);
+
+  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->printer_combo), dialog->printer_list);
+  printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
+
+  /* Load data */
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+  load_print_backends (dialog);
+  dialog->internal_change = FALSE;
+}
+
+static void
+gtk_page_setup_unix_dialog_finalize (GObject *object)
+{
+  GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
+  GList *node;
+
+  if (dialog->request_details_tag)
+    {
+      g_signal_handler_disconnect (dialog->request_details_printer,
+                                   dialog->request_details_tag);
+      g_object_unref (dialog->request_details_printer);
+      dialog->request_details_printer = NULL;
+      dialog->request_details_tag = 0;
+    }
+
+  g_clear_object (&dialog->printer_list);
+  g_clear_object (&dialog->page_setup_list);
+  g_clear_object (&dialog->custom_paper_list);
+  g_clear_object (&dialog->manage_papers_list);
+
+  if (dialog->print_settings)
+    {
+      g_object_unref (dialog->print_settings);
+      dialog->print_settings = NULL;
+    }
+
+  for (node = dialog->print_backends; node != NULL; node = node->next)
+    gtk_print_backend_destroy (GTK_PRINT_BACKEND (node->data));
+  g_list_free_full (dialog->print_backends, g_object_unref);
+  dialog->print_backends = NULL;
+
+  G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
+}
+
+static void
+load_print_backends (GtkPageSetupUnixDialog *dialog)
+{
+  GListModel *full_list;
+  GListStore *printer_list_list;
+  GList *node;
+
+  full_list = gtk_filter_list_model_get_model (GTK_FILTER_LIST_MODEL (dialog->printer_list));
+  printer_list_list = G_LIST_STORE (gtk_flatten_list_model_get_model (GTK_FLATTEN_LIST_MODEL (full_list)));
+
+  if (g_module_supported ())
+    dialog->print_backends = gtk_print_backend_load_modules ();
+
+  for (node = dialog->print_backends; node != NULL; node = node->next)
+    {
+      GtkPrintBackend *backend = node->data;
+      g_list_store_append (printer_list_list, gtk_print_backend_get_printers (backend));
+    }
+}
+
+static GtkPageSetup *
+get_current_page_setup (GtkPageSetupUnixDialog *dialog)
+{
+  guint selected;
+  GListModel *model;
+
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->paper_size_combo));
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+  if (selected != GTK_INVALID_LIST_POSITION)
+    return g_list_model_get_item (model, selected);
+
+  return gtk_page_setup_new ();
+}
+
+static gboolean
+page_setup_is_equal (GtkPageSetup *a,
+                     GtkPageSetup *b)
+{
+  return
+    gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+                             gtk_page_setup_get_paper_size (b)) &&
+    gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
+}
+
+static gboolean
+page_setup_is_same_size (GtkPageSetup *a,
+                         GtkPageSetup *b)
+{
+  return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+                                  gtk_page_setup_get_paper_size (b));
+}
+
+static gboolean
+set_paper_size (GtkPageSetupUnixDialog *dialog,
+                GtkPageSetup           *page_setup,
+                gboolean                size_only,
+                gboolean                add_item)
+{
+  GListModel *model;
+  GtkPageSetup *list_page_setup;
+  guint i;
+
+  if (page_setup == NULL)
+    return FALSE;
+
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+  for (i = 0; i < g_list_model_get_n_items (model); i++)
+    {
+      list_page_setup = g_list_model_get_item (model, i);
+      if (list_page_setup == NULL)
+        continue;
+
+      if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
+          (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
+        {
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+          g_object_unref (list_page_setup);
+          return TRUE;
+        }
+
+      g_object_unref (list_page_setup);
+    }
+
+  if (add_item)
+    {
+      i = g_list_model_get_n_items (model);
+      g_list_store_append (dialog->page_setup_list, page_setup);
+      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
+                               GtkPrinter             *printer)
+{
+  GList *list, *l;
+  GtkPageSetup *current_page_setup, *page_setup;
+  GtkPaperSize *paper_size;
+  int i;
+
+  g_list_store_remove_all (dialog->page_setup_list);
+
+  if (printer == NULL)
+    {
+      for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
+        {
+          page_setup = gtk_page_setup_new ();
+          paper_size = gtk_paper_size_new (common_paper_sizes[i]);
+          gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
+          gtk_paper_size_free (paper_size);
+
+          g_list_store_append (dialog->page_setup_list, page_setup);
+          g_object_unref (page_setup);
+        }
+    }
+  else
+    {
+      list = gtk_printer_list_papers (printer);
+      /* TODO: We should really sort this list so interesting size
+         are at the top */
+      for (l = list; l != NULL; l = l->next)
+        {
+          page_setup = l->data;
+          g_list_store_append (dialog->page_setup_list, page_setup);
+          g_object_unref (page_setup);
+        }
+      g_list_free (list);
+    }
+
+  current_page_setup = NULL;
+
+  /* When selecting a different printer, select its default paper size */
+  if (printer != NULL)
+    current_page_setup = gtk_printer_get_default_page_size (printer);
+
+  if (current_page_setup == NULL)
+    current_page_setup = get_current_page_setup (dialog);
+
+  if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
+    set_paper_size (dialog, current_page_setup, TRUE, TRUE);
+
+  if (current_page_setup)
+    g_object_unref (current_page_setup);
+}
+
+static void
+printer_changed_finished_callback (GtkPrinter             *printer,
+                                   gboolean                success,
+                                   GtkPageSetupUnixDialog *dialog)
+{
+  g_signal_handler_disconnect (dialog->request_details_printer,
+                               dialog->request_details_tag);
+  g_object_unref (dialog->request_details_printer);
+  dialog->request_details_tag = 0;
+  dialog->request_details_printer = NULL;
+
+  if (success)
+    fill_paper_sizes_from_printer (dialog, printer);
+
+}
+
+static void
+printer_changed_callback (GtkDropDown            *combo_box,
+                          GParamSpec             *pspec,
+                          GtkPageSetupUnixDialog *dialog)
+{
+  GtkPrinter *printer;
+  guint selected;
+
+  if (dialog->request_details_tag)
+    {
+      g_signal_handler_disconnect (dialog->request_details_printer,
+                                   dialog->request_details_tag);
+      g_object_unref (dialog->request_details_printer);
+      dialog->request_details_printer = NULL;
+      dialog->request_details_tag = 0;
+    }
+
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->printer_combo));
+  if (selected != GTK_INVALID_LIST_POSITION)
+    {
+      GListModel *model;
+
+      model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->printer_combo));
+      printer = g_list_model_get_item (model, selected);
+      if (strcmp (gtk_printer_get_name (printer), _("Any Printer")) == 0)
+        g_clear_object (&printer);
+
+      if (printer == NULL ||
+          gtk_printer_has_details (printer))
+        fill_paper_sizes_from_printer (dialog, printer);
+      else
+        {
+          dialog->request_details_printer = g_object_ref (printer);
+          dialog->request_details_tag =
+            g_signal_connect (printer, "details-acquired",
+                              G_CALLBACK (printer_changed_finished_callback), dialog);
+          gtk_printer_request_details (printer);
+        }
+
+      if (printer)
+        g_object_unref (printer);
+
+      if (dialog->print_settings)
+        {
+          const char *name = NULL;
+
+          if (printer)
+            name = gtk_printer_get_name (printer);
+
+          gtk_print_settings_set (dialog->print_settings,
+                                  "format-for-printer", name);
+        }
+    }
+}
+
+/* We do this munging because we don't want to show zero digits
+   after the decimal point, and not to many such digits if they
+   are nonzero. I wish printf let you specify max precision for %f... */
+static char *
+double_to_string (double d,
+                  GtkUnit unit)
+{
+  char *val, *p;
+  struct lconv *locale_data;
+  const char *decimal_point;
+  int decimal_point_len;
+
+  locale_data = localeconv ();
+  decimal_point = locale_data->decimal_point;
+  decimal_point_len = strlen (decimal_point);
+
+  /* Max two decimal digits for inch, max one for mm */
+  if (unit == GTK_UNIT_INCH)
+    val = g_strdup_printf ("%.2f", d);
+  else
+    val = g_strdup_printf ("%.1f", d);
+
+  if (strstr (val, decimal_point))
+    {
+      p = val + strlen (val) - 1;
+      while (*p == '0')
+        p--;
+      if (p - val + 1 >= decimal_point_len &&
+          strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
+        p -= decimal_point_len;
+      p[1] = '\0';
+    }
+
+  return val;
+}
+
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
+                                 int        response_id,
+                                 gpointer   user_data)
+{
+  GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (user_data);
+  GtkPageSetup *last_page_setup;
+
+  dialog->internal_change = TRUE;
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+  printer_changed_callback (GTK_DROP_DOWN (dialog->printer_combo), NULL, dialog);
+  dialog->internal_change = FALSE;
+
+  if (dialog->last_setup)
+    last_page_setup = g_object_ref (dialog->last_setup);
+  else
+    last_page_setup = gtk_page_setup_new (); /* "good" default */
+  set_paper_size (dialog, last_page_setup, FALSE, TRUE);
+  g_object_unref (last_page_setup);
+
+  gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
+}
+
+static void
+paper_size_changed (GtkDropDown            *combo_box,
+                    GParamSpec             *pspec,
+                    GtkPageSetupUnixDialog *dialog)
+{
+  GtkPageSetup *page_setup, *last_page_setup;
+  guint selected;
+  GtkUnit unit;
+  char *str, *w, *h;
+  char *top, *bottom, *left, *right;
+  GtkLabel *label;
+  const char *unit_str;
+
+  if (dialog->internal_change)
+    return;
+
+  label = GTK_LABEL (dialog->paper_size_label);
+
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
+  if (selected != GTK_INVALID_LIST_POSITION)
+    {
+      GListModel *papers, *model;
+
+      papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+      page_setup = g_list_model_get_item (papers, selected);
+      model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
+
+      if (model == G_LIST_MODEL (dialog->manage_papers_list))
+        {
+          GtkWidget *custom_paper_dialog;
+
+          /* Change from "manage" menu item to last value */
+          if (dialog->last_setup)
+            last_page_setup = g_object_ref (dialog->last_setup);
+          else
+            last_page_setup = gtk_page_setup_new (); /* "good" default */
+          set_paper_size (dialog, last_page_setup, FALSE, TRUE);
+          g_object_unref (last_page_setup);
+
+          /* And show the custom paper dialog */
+          custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), NULL);
+          g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
+          gtk_window_present (GTK_WINDOW (custom_paper_dialog));
+
+          g_object_unref (page_setup);
+
+          return;
+        }
+
+      if (dialog->last_setup)
+        g_object_unref (dialog->last_setup);
+
+      dialog->last_setup = g_object_ref (page_setup);
+
+      unit = _gtk_print_get_default_user_units ();
+
+      if (unit == GTK_UNIT_MM)
+        unit_str = _("mm");
+      else
+        unit_str = _("inch");
+
+      w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
+                            unit);
+      h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
+                            unit);
+      str = g_strdup_printf ("%s × %s %s", w, h, unit_str);
+      g_free (w);
+      g_free (h);
+
+      gtk_label_set_text (label, str);
+      g_free (str);
+
+      top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
+      bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
+      left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
+      right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
+
+      str = g_strdup_printf (_("Margins:\n"
+                               " Left: %s %s\n"
+                               " Right: %s %s\n"
+                               " Top: %s %s\n"
+                               " Bottom: %s %s"
+                               ),
+                             left, unit_str,
+                             right, unit_str,
+                             top, unit_str,
+                             bottom, unit_str);
+      g_free (top);
+      g_free (bottom);
+      g_free (left);
+      g_free (right);
+
+      gtk_widget_set_tooltip_text (dialog->paper_size_label, str);
+      g_free (str);
+
+      g_object_unref (page_setup);
+    }
+  else
+    {
+      gtk_label_set_text (label, "");
+      gtk_widget_set_tooltip_text (dialog->paper_size_label, NULL);
+      if (dialog->last_setup)
+        g_object_unref (dialog->last_setup);
+      dialog->last_setup = NULL;
+    }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_new:
+ * @title: (nullable): the title of the dialog
+ * @parent: (nullable): transient parent of the dialog
+ *
+ * Creates a new page setup dialog.
+ *
+ * Returns: the new `GtkPageSetupUnixDialog`
+ */
+GtkWidget *
+gtk_page_setup_unix_dialog_new (const char *title,
+                                GtkWindow   *parent)
+{
+  GtkWidget *result;
+
+  if (title == NULL)
+    title = _("Page Setup");
+
+  result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
+                         "title", title,
+                         NULL);
+
+  if (parent)
+    gtk_window_set_transient_for (GTK_WINDOW (result), parent);
+
+  return result;
+}
+
+static GtkPageOrientation
+get_orientation (GtkPageSetupUnixDialog *dialog)
+{
+  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->portrait_radio)))
+    return GTK_PAGE_ORIENTATION_PORTRAIT;
+  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->landscape_radio)))
+    return GTK_PAGE_ORIENTATION_LANDSCAPE;
+  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio)))
+    return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
+  return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
+}
+
+static void
+set_orientation (GtkPageSetupUnixDialog *dialog,
+                 GtkPageOrientation      orientation)
+{
+  switch (orientation)
+    {
+    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_portrait_radio), TRUE);
+      break;
+    case GTK_PAGE_ORIENTATION_PORTRAIT:
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->portrait_radio), TRUE);
+      break;
+    case GTK_PAGE_ORIENTATION_LANDSCAPE:
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->landscape_radio), TRUE);
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_landscape_radio), TRUE);
+      break;
+    default:
+      break;
+    }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_set_page_setup:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Sets the `GtkPageSetup` from which the page setup
+ * dialog takes its values.
+ */
+void
+gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
+                                           GtkPageSetup           *page_setup)
+{
+  if (page_setup)
+    {
+      set_paper_size (dialog, page_setup, FALSE, TRUE);
+      set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
+    }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_get_page_setup:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ *
+ * Gets the currently selected page setup from the dialog.
+ *
+ * Returns: (transfer none): the current page setup
+ */
+GtkPageSetup *
+gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
+{
+  GtkPageSetup *page_setup;
+
+  page_setup = get_current_page_setup (dialog);
+
+  gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
+
+  return page_setup;
+}
+
+static gboolean
+set_active_printer (GtkPageSetupUnixDialog *dialog,
+                    const char             *printer_name)
+{
+  guint i, n;
+  GtkPrinter *printer;
+
+  if (!printer_name)
+    return FALSE;
+
+  for (i = 0, n = g_list_model_get_n_items (dialog->printer_list); i < n; i++)
+    {
+      printer = g_list_model_get_item (dialog->printer_list, i);
+
+      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+        {
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->printer_combo), i);
+          g_object_unref (printer);
+
+          return TRUE;
+        }
+
+      g_object_unref (printer);
+    }
+
+  return FALSE;
+}
+
+/**
+ * gtk_page_setup_unix_dialog_set_print_settings:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ * @print_settings: (nullable): a `GtkPrintSettings`
+ *
+ * Sets the `GtkPrintSettings` from which the page setup dialog
+ * takes its values.
+ */
+void
+gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
+                                               GtkPrintSettings       *print_settings)
+{
+  const char *format_for_printer;
+
+  if (dialog->print_settings == print_settings) return;
+
+  if (dialog->print_settings)
+    g_object_unref (dialog->print_settings);
+
+  dialog->print_settings = print_settings;
+
+  if (print_settings)
+    {
+      g_object_ref (print_settings);
+
+      format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
+
+      /* Set printer if in list, otherwise set when
+       * that printer is added
+       */
+      set_active_printer (dialog, format_for_printer);
+    }
+}
+
+/**
+ * gtk_page_setup_unix_dialog_get_print_settings:
+ * @dialog: a `GtkPageSetupUnixDialog`
+ *
+ * Gets the current print settings from the dialog.
+ *
+ * Returns: (transfer none) (nullable): the current print settings
+ **/
+GtkPrintSettings *
+gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
+{
+  return dialog->print_settings;
+}
diff --git a/gtk/print/gtkpagesetupunixdialog.h b/gtk/print/gtkpagesetupunixdialog.h
new file mode 100644 (file)
index 0000000..84a42cb
--- /dev/null
@@ -0,0 +1,53 @@
+/* GtkPageSetupUnixDialog
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PAGE_SETUP_UNIX_DIALOG                  (gtk_page_setup_unix_dialog_get_type ())
+#define GTK_PAGE_SETUP_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialog))
+#define GTK_IS_PAGE_SETUP_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG))
+
+
+typedef struct _GtkPageSetupUnixDialog GtkPageSetupUnixDialog;
+
+
+GDK_AVAILABLE_IN_ALL
+GType            gtk_page_setup_unix_dialog_get_type           (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkWidget *       gtk_page_setup_unix_dialog_new                (const char             *title,
+                                                                GtkWindow              *parent);
+GDK_AVAILABLE_IN_ALL
+void              gtk_page_setup_unix_dialog_set_page_setup     (GtkPageSetupUnixDialog *dialog,
+                                                                GtkPageSetup           *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup *    gtk_page_setup_unix_dialog_get_page_setup     (GtkPageSetupUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void              gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
+                                                                GtkPrintSettings       *print_settings);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings *gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprint-win32.c b/gtk/print/gtkprint-win32.c
new file mode 100644 (file)
index 0000000..76b1d69
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MSC_VER
+#ifndef _WIN32_WINNT
+/* Vista or newer */
+#define _WIN32_WINNT 0x0600
+#endif
+#ifndef WINVER
+#define WINVER _WIN32_WINNT
+#endif
+#endif
+
+#include "config.h"
+#include "gtkprint-win32.h"
+
+void
+gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames)
+{
+  g_free (devnames->driver);
+  g_free (devnames->device);
+  g_free (devnames->output);
+  g_free (devnames);
+}
+
+GtkPrintWin32Devnames *
+gtk_print_win32_devnames_from_win32 (HGLOBAL global)
+{
+  LPDEVNAMES win = GlobalLock (global);
+  gunichar2 *data = (gunichar2 *)win;
+  GtkPrintWin32Devnames *devnames = g_new (GtkPrintWin32Devnames, 1);
+  
+  devnames->driver = g_utf16_to_utf8 (data + win->wDriverOffset, 
+                                     -1, NULL, NULL, NULL);
+  devnames->device = g_utf16_to_utf8 (data + win->wDeviceOffset, 
+                                     -1, NULL, NULL, NULL);
+  devnames->output = g_utf16_to_utf8 (data + win->wOutputOffset, 
+                                     -1, NULL, NULL, NULL);
+  devnames->flags = win->wDefault;
+  
+  GlobalUnlock (global);
+
+  return devnames;
+}
+
+HGLOBAL 
+gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames)
+{
+  HGLOBAL global;
+  LPDEVNAMES windevnames;
+  gunichar2 *data;
+  gunichar2 *driver, *device, *output;
+  glong driver_len, device_len, output_len;
+  int i;
+
+  driver = g_utf8_to_utf16 (devnames->driver, -1, NULL, &driver_len, NULL);
+  device = g_utf8_to_utf16 (devnames->device, -1, NULL, &device_len, NULL);
+  output = g_utf8_to_utf16 (devnames->output, -1, NULL, &output_len, NULL);
+
+  global = GlobalAlloc (GMEM_MOVEABLE, 
+                       sizeof (DEVNAMES) + 
+                       (driver_len + 1) * 2 + 
+                       (device_len + 1) * 2 +
+                       (output_len + 1) * 2);
+
+  windevnames = GlobalLock (global);
+  data = (gunichar2 *)windevnames;
+  i = sizeof(DEVNAMES) / sizeof (gunichar2);
+
+  windevnames->wDriverOffset = i;
+  memcpy (data + i, driver, (driver_len + 1) * sizeof (gunichar2));
+  i += driver_len + 1;
+  windevnames->wDeviceOffset = i;
+  memcpy (data + i, device, (device_len + 1) * sizeof (gunichar2));
+  i += device_len + 1;
+  windevnames->wOutputOffset = i;
+  memcpy (data + i, output, (output_len + 1) * sizeof (gunichar2));
+  i += output_len + 1;
+  windevnames->wDefault = devnames->flags;
+  GlobalUnlock (global);
+
+  g_free (driver);
+  g_free (device);
+  g_free (output);
+
+  return global;
+}
+
+HGLOBAL 
+gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer_name)
+{
+  HGLOBAL global;
+  GtkPrintWin32Devnames *devnames;
+
+  devnames = gtk_print_win32_devnames_from_printer_name(printer_name);
+  if (devnames)
+    {
+      global = gtk_print_win32_devnames_to_win32 (devnames);
+      gtk_print_win32_devnames_free (devnames);
+    }
+  else
+    global = NULL;
+
+  return global;
+}
+
+/*
+ * Used to get printer device information from a printer name.  This
+ * can fail if the user has no right to read printer properties, so
+ * this function can return NULL.
+ */
+GtkPrintWin32Devnames *
+gtk_print_win32_devnames_from_printer_name (const char *printer_name)
+{
+  HANDLE hprinter;
+  gunichar2* win32_printer_name;
+  GtkPrintWin32Devnames *devnames;
+
+  win32_printer_name = g_utf8_to_utf16 (printer_name, -1, NULL, NULL, NULL);
+  if (OpenPrinterW (win32_printer_name, &hprinter, NULL))
+    {
+      DWORD needed;
+      PRINTER_INFO_2W* printer_info;
+
+      GetPrinterW (hprinter, 2, NULL, 0, &needed);
+      printer_info = (PRINTER_INFO_2W* )g_malloc ((gsize) needed);
+      GetPrinterW (hprinter, 2, (LPBYTE) printer_info, needed, &needed);
+      devnames = g_new (GtkPrintWin32Devnames, 1);
+      devnames->driver = g_utf16_to_utf8 (printer_info->pDriverName, -1, NULL, NULL, NULL);
+      devnames->device = g_strdup (printer_name);
+      devnames->output = g_utf16_to_utf8 (printer_info->pPortName, -1, NULL, NULL, NULL);
+      devnames->flags  = 0;
+      ClosePrinter (hprinter);
+      g_free (printer_info);
+    }
+  else
+    {
+      /* Could not open printer */
+      devnames = NULL;
+    }
+  g_free (win32_printer_name);
+
+  return devnames;
+}
diff --git a/gtk/print/gtkprint-win32.h b/gtk/print/gtkprint-win32.h
new file mode 100644 (file)
index 0000000..626e15d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "win32/gdkwin32.h"
+
+G_BEGIN_DECLS
+
+#ifndef START_PAGE_GENERAL
+#define START_PAGE_GENERAL 0xffffffff
+#endif
+
+#ifndef PD_RESULT_CANCEL
+#define PD_RESULT_CANCEL  0
+#define PD_RESULT_PRINT  1
+#define PD_RESULT_APPLY  2
+#endif
+
+#ifndef PD_NOCURRENTPAGE
+#define PD_NOCURRENTPAGE  0x00800000
+#endif
+
+#ifndef PD_CURRENTPAGE
+#define PD_CURRENTPAGE  0x00400000
+#endif
+
+typedef struct {
+  char *driver;
+  char *device;
+  char *output;
+  int flags;
+} GtkPrintWin32Devnames;
+
+GDK_AVAILABLE_IN_ALL
+void gtk_print_win32_devnames_free (GtkPrintWin32Devnames *devnames);
+GDK_AVAILABLE_IN_ALL
+GtkPrintWin32Devnames *gtk_print_win32_devnames_from_win32 (HGLOBAL global);
+GDK_AVAILABLE_IN_ALL
+GtkPrintWin32Devnames *gtk_print_win32_devnames_from_printer_name (const char *printer);
+GDK_AVAILABLE_IN_ALL
+HGLOBAL gtk_print_win32_devnames_to_win32 (const GtkPrintWin32Devnames *devnames);
+GDK_AVAILABLE_IN_ALL
+HGLOBAL gtk_print_win32_devnames_to_win32_from_printer_name (const char *printer);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprintbackend.c b/gtk/print/gtkprintbackend.c
new file mode 100644 (file)
index 0000000..1fd4c35
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <string.h>
+
+#include <gmodule.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkdebug.h"
+#include "gtkmodulesprivate.h"
+#include "gtkmarshalers.h"
+#include "gtkprivate.h"
+#include "gtkprintbackendprivate.h"
+
+
+static void gtk_print_backend_finalize     (GObject      *object);
+static void gtk_print_backend_dispose      (GObject      *object);
+static void gtk_print_backend_set_property (GObject      *object,
+                                            guint         prop_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec);
+static void gtk_print_backend_get_property (GObject      *object,
+                                            guint         prop_id,
+                                            GValue       *value,
+                                            GParamSpec   *pspec);
+
+struct _GtkPrintBackendPrivate
+{
+  GListStore *printers;
+  guint printer_list_requested : 1;
+  guint printer_list_done : 1;
+  GtkPrintBackendStatus status;
+  char **auth_info_required;
+  char **auth_info;
+  gboolean store_auth_info;
+};
+
+enum {
+  PRINTER_LIST_CHANGED,
+  PRINTER_LIST_DONE,
+  PRINTER_ADDED,
+  PRINTER_REMOVED,
+  PRINTER_STATUS_CHANGED,
+  REQUEST_PASSWORD,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum 
+{ 
+  PROP_ZERO,
+  PROP_STATUS
+};
+
+static GObjectClass *backend_parent_class;
+
+GQuark
+gtk_print_backend_error_quark (void)
+{
+  static GQuark quark = 0;
+  if (quark == 0)
+    quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
+  return quark;
+}
+
+void
+gtk_print_backends_init (void)
+{
+  GIOExtensionPoint *ep;
+  GIOModuleScope *scope;
+  char **paths;
+  int i;
+
+  GTK_DEBUG (MODULES, "Registering extension point %s", GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+
+  ep = g_io_extension_point_register (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+  g_io_extension_point_set_required_type (ep, GTK_TYPE_PRINT_BACKEND);
+
+  scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
+
+  paths = _gtk_get_module_path ("printbackends");
+  for (i = 0; paths[i]; i++)
+    {
+      GTK_DEBUG (MODULES, "Scanning io modules in %s", paths[i]);
+      g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
+    }
+  g_strfreev (paths);
+
+  g_io_module_scope_free (scope);
+
+  if (GTK_DEBUG_CHECK (MODULES))
+    {
+      GList *list, *l;
+
+      list = g_io_extension_point_get_extensions (ep);
+      for (l = list; l; l = l->next)
+        {
+          GIOExtension *ext = l->data;
+          g_print ("extension: %s: type %s\n",
+                   g_io_extension_get_name (ext),
+                   g_type_name (g_io_extension_get_type (ext)));
+        }
+    }
+}
+
+/**
+ * gtk_print_backend_load_modules:
+ *
+ * Returns: (element-type GtkPrintBackend) (transfer container):
+ */
+GList *
+gtk_print_backend_load_modules (void)
+{
+  GList *result;
+  GtkPrintBackend *backend;
+  char *setting;
+  char **backends;
+  int i;
+  GtkSettings *settings;
+  GIOExtensionPoint *ep;
+
+  result = NULL;
+
+  ep = g_io_extension_point_lookup (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
+
+  settings = gtk_settings_get_default ();
+  if (settings)
+    g_object_get (settings, "gtk-print-backends", &setting, NULL);
+  else
+    setting = g_strdup (GTK_PRINT_BACKENDS);
+
+  backends = g_strsplit (setting, ",", -1);
+
+  for (i = 0; backends[i]; i++)
+    {
+      GIOExtension *ext;
+      GType type;
+
+      ext = g_io_extension_point_get_extension_by_name (ep, backends[i]);
+      if (!ext)
+        continue;
+
+      GTK_DEBUG (PRINTING, "Found %s print backend", backends[i]);
+
+      type = g_io_extension_get_type (ext);
+      backend = g_object_new (type, NULL);
+      result = g_list_append (result, backend);
+    }
+
+  g_strfreev (backends);
+  g_free (setting);
+
+  return result;
+}
+
+/*****************************************
+ *             GtkPrintBackend           *
+ *****************************************/
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
+
+static void                 fallback_printer_request_details       (GtkPrinter          *printer);
+static gboolean             fallback_printer_mark_conflicts        (GtkPrinter          *printer,
+                                                                   GtkPrinterOptionSet *options);
+static gboolean             fallback_printer_get_hard_margins      (GtkPrinter          *printer,
+                                                                    double              *top,
+                                                                    double              *bottom,
+                                                                    double              *left,
+                                                                    double              *right);
+static gboolean             fallback_printer_get_hard_margins_for_paper_size (GtkPrinter          *printer,
+                                                                             GtkPaperSize        *paper_size,
+                                                                             double              *top,
+                                                                             double              *bottom,
+                                                                             double              *left,
+                                                                             double              *right);
+static GList *              fallback_printer_list_papers           (GtkPrinter          *printer);
+static GtkPageSetup *       fallback_printer_get_default_page_size (GtkPrinter          *printer);
+static GtkPrintCapabilities fallback_printer_get_capabilities      (GtkPrinter          *printer);
+static void                 request_password                       (GtkPrintBackend     *backend,
+                                                                    gpointer             auth_info_required,
+                                                                    gpointer             auth_info_default,
+                                                                    gpointer             auth_info_display,
+                                                                    gpointer             auth_info_visible,
+                                                                    const char          *prompt,
+                                                                    gboolean             can_store_auth_info);
+
+static void
+gtk_print_backend_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+  GtkPrintBackendPrivate *priv = backend->priv;
+
+  switch (prop_id)
+    {
+    case PROP_STATUS:
+      priv->status = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_print_backend_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+  GtkPrintBackendPrivate *priv = backend->priv;
+
+  switch (prop_id)
+    {
+    case PROP_STATUS:
+      g_value_set_int (value, priv->status);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_print_backend_class_init (GtkPrintBackendClass *class)
+{
+  GObjectClass *object_class;
+  object_class = (GObjectClass *) class;
+
+  backend_parent_class = g_type_class_peek_parent (class);
+  
+  object_class->finalize = gtk_print_backend_finalize;
+  object_class->dispose = gtk_print_backend_dispose;
+  object_class->set_property = gtk_print_backend_set_property;
+  object_class->get_property = gtk_print_backend_get_property;
+
+  class->printer_request_details = fallback_printer_request_details;
+  class->printer_mark_conflicts = fallback_printer_mark_conflicts;
+  class->printer_get_hard_margins = fallback_printer_get_hard_margins;
+  class->printer_get_hard_margins_for_paper_size = fallback_printer_get_hard_margins_for_paper_size;
+  class->printer_list_papers = fallback_printer_list_papers;
+  class->printer_get_default_page_size = fallback_printer_get_default_page_size;
+  class->printer_get_capabilities = fallback_printer_get_capabilities;
+  class->request_password = request_password;
+  
+  g_object_class_install_property (object_class, 
+                                   PROP_STATUS,
+                                   g_param_spec_int ("status", NULL, NULL,
+                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+                                                     GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
+                                                     GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+                                                     GTK_PARAM_READWRITE)); 
+  
+  signals[PRINTER_LIST_CHANGED] =
+    g_signal_new (I_("printer-list-changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+  signals[PRINTER_LIST_DONE] =
+    g_signal_new (I_("printer-list-done"),
+                   G_TYPE_FROM_CLASS (class),
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
+                   NULL, NULL,
+                   NULL,
+                   G_TYPE_NONE, 0);
+  signals[PRINTER_ADDED] =
+    g_signal_new (I_("printer-added"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+  signals[PRINTER_REMOVED] =
+    g_signal_new (I_("printer-removed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+  signals[PRINTER_STATUS_CHANGED] =
+    g_signal_new (I_("printer-status-changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
+  signals[REQUEST_PASSWORD] =
+    g_signal_new (I_("request-password"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
+                 NULL, NULL, NULL,
+                 G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
+                 G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
+}
+
+static void
+gtk_print_backend_init (GtkPrintBackend *backend)
+{
+  GtkPrintBackendPrivate *priv;
+
+  priv = backend->priv = gtk_print_backend_get_instance_private (backend);
+
+  priv->printers = g_list_store_new (GTK_TYPE_PRINTER);
+  priv->auth_info_required = NULL;
+  priv->auth_info = NULL;
+}
+
+static void
+gtk_print_backend_dispose (GObject *object)
+{
+  GtkPrintBackend *backend;
+  GtkPrintBackendPrivate *priv;
+
+  backend = GTK_PRINT_BACKEND (object);
+  priv = backend->priv;
+
+  /* We unref the printers in dispose, not in finalize so that
+   * we can break refcount cycles with gtk_print_backend_destroy 
+   */
+  g_list_store_remove_all (priv->printers);
+
+  backend_parent_class->dispose (object);
+}
+
+static void
+gtk_print_backend_finalize (GObject *object)
+{
+  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+  GtkPrintBackendPrivate *priv = backend->priv;
+
+  g_clear_object (&priv->printers);
+
+  backend_parent_class->finalize (object);
+}
+
+static void
+fallback_printer_request_details (GtkPrinter *printer)
+{
+}
+
+static gboolean
+fallback_printer_mark_conflicts (GtkPrinter          *printer,
+                                 GtkPrinterOptionSet *options)
+{
+  return FALSE;
+}
+
+static gboolean
+fallback_printer_get_hard_margins (GtkPrinter *printer,
+                                  double     *top,
+                                  double     *bottom,
+                                  double     *left,
+                                  double     *right)
+{
+  return FALSE;
+}
+
+static gboolean
+fallback_printer_get_hard_margins_for_paper_size (GtkPrinter   *printer,
+                                                 GtkPaperSize *paper_size,
+                                                 double       *top,
+                                                 double       *bottom,
+                                                 double       *left,
+                                                 double       *right)
+{
+  return FALSE;
+}
+
+static GList *
+fallback_printer_list_papers (GtkPrinter *printer)
+{
+  return NULL;
+}
+
+static GtkPageSetup *
+fallback_printer_get_default_page_size (GtkPrinter *printer)
+{
+  return NULL;
+}
+
+static GtkPrintCapabilities
+fallback_printer_get_capabilities (GtkPrinter *printer)
+{
+  return 0;
+}
+
+void
+gtk_print_backend_add_printer (GtkPrintBackend *backend,
+                              GtkPrinter      *printer)
+{
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+  g_list_store_append (backend->priv->printers, printer);
+}
+
+void
+gtk_print_backend_remove_printer (GtkPrintBackend *backend,
+                                 GtkPrinter      *printer)
+{
+  guint position;
+  
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+  if (g_list_store_find (backend->priv->printers, printer, &position))
+    g_list_store_remove (backend->priv->printers, position);
+}
+
+void
+gtk_print_backend_set_list_done (GtkPrintBackend *backend)
+{
+  if (!backend->priv->printer_list_done)
+    {
+      backend->priv->printer_list_done = TRUE;
+      g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
+    }
+}
+
+
+/**
+ * gtk_print_backend_get_printer_list:
+ *
+ * Returns the current list of printers.
+ *
+ * Returns: (element-type GtkPrinter) (transfer container):
+ *   A list of `GtkPrinter` objects
+ */
+GList *
+gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
+{
+  GList *result = NULL;
+  guint i;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
+    {
+      GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
+      result = g_list_prepend (result, printer);
+      g_object_unref (printer);
+    }
+
+  if (!backend->priv->printer_list_requested)
+    {
+      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+       GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+      backend->priv->printer_list_requested = TRUE;
+    }
+
+  return result;
+}
+
+GListModel *
+gtk_print_backend_get_printers (GtkPrintBackend *backend)
+{
+  if (!backend->priv->printer_list_requested)
+    {
+      if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
+       GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
+      backend->priv->printer_list_requested = TRUE;
+    }
+
+  return G_LIST_MODEL (backend->priv->printers);
+}
+
+gboolean
+gtk_print_backend_printer_list_is_done (GtkPrintBackend *backend)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), TRUE);
+
+  return backend->priv->printer_list_done;
+}
+
+GtkPrinter *
+gtk_print_backend_find_printer (GtkPrintBackend *backend,
+                                const char      *printer_name)
+{
+  GtkPrinter *result = NULL;
+  guint i;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
+
+  for (i = 0; !result && i < g_list_model_get_n_items (G_LIST_MODEL (backend->priv->printers)); i++)
+    {
+      GtkPrinter *printer = g_list_model_get_item (G_LIST_MODEL (backend->priv->printers), i);
+      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+        result = printer;
+      g_object_unref (printer);
+    }
+
+  return result;  
+}
+
+void
+gtk_print_backend_print_stream (GtkPrintBackend        *backend,
+                                GtkPrintJob            *job,
+                                GIOChannel             *data_io,
+                                GtkPrintJobCompleteFunc callback,
+                                gpointer                user_data,
+                               GDestroyNotify          dnotify)
+{
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+  GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
+                                                      job,
+                                                      data_io,
+                                                      callback,
+                                                      user_data,
+                                                      dnotify);
+}
+
+void 
+gtk_print_backend_set_password (GtkPrintBackend  *backend,
+                                char            **auth_info_required,
+                                char            **auth_info,
+                                gboolean          store_auth_info)
+{
+  g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
+
+  if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
+    GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
+                                                         auth_info_required,
+                                                         auth_info,
+                                                         store_auth_info);
+}
+
+static void
+store_auth_info_toggled (GtkCheckButton *chkbtn,
+                         gpointer        user_data)
+{
+  gboolean *data = (gboolean *) user_data;
+  *data = gtk_check_button_get_active (GTK_CHECK_BUTTON (chkbtn));
+}
+
+static void
+store_entry (GtkEntry  *entry,
+             gpointer   user_data)
+{
+  char **data = (char **) user_data;
+
+  if (*data != NULL)
+    {
+      memset (*data, 0, strlen (*data));
+      g_free (*data);
+    }
+
+  *data = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
+}
+
+static void
+password_dialog_response (GtkWidget       *dialog,
+                          int              response_id,
+                          GtkPrintBackend *backend)
+{
+  GtkPrintBackendPrivate *priv = backend->priv;
+  int i, auth_info_len;
+
+  if (response_id == GTK_RESPONSE_OK)
+    gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
+  else
+    gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
+
+  /* We want to clear the data before freeing it */
+  auth_info_len = g_strv_length (priv->auth_info_required);
+  for (i = 0; i < auth_info_len; i++)
+    {
+      if (priv->auth_info[i] != NULL)
+        {
+          memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
+          g_free (priv->auth_info[i]);
+          priv->auth_info[i] = NULL;
+        }
+    }
+
+  g_clear_pointer (&priv->auth_info, g_free);
+  g_clear_pointer (&priv->auth_info_required, g_strfreev);
+
+  gtk_window_destroy (GTK_WINDOW (dialog));
+
+  g_object_unref (backend);
+}
+
+static void
+request_password (GtkPrintBackend  *backend,
+                  gpointer          auth_info_required,
+                  gpointer          auth_info_default,
+                  gpointer          auth_info_display,
+                  gpointer          auth_info_visible,
+                  const char       *prompt,
+                  gboolean          can_store_auth_info)
+{
+  GtkPrintBackendPrivate *priv = backend->priv;
+  GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
+  GtkWidget *focus = NULL;
+  GtkWidget *content_area;
+  char      *markup;
+  int        length;
+  int        i;
+  char     **ai_required = (char **) auth_info_required;
+  char     **ai_default = (char **) auth_info_default;
+  char     **ai_display = (char **) auth_info_display;
+  gboolean  *ai_visible = (gboolean *) auth_info_visible;
+
+  priv->auth_info_required = g_strdupv (ai_required);
+  length = g_strv_length (ai_required);
+  priv->auth_info = g_new0 (char *, length + 1);
+  priv->store_auth_info = FALSE;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, 
+                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                         _("_OK"), GTK_RESPONSE_OK,
+                                         NULL);
+
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+  main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+  /* Left */
+  icon = gtk_image_new_from_icon_name ("dialog-password-symbolic");
+  gtk_image_set_icon_size (GTK_IMAGE (icon), GTK_ICON_SIZE_LARGE);
+  gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
+  gtk_widget_set_valign (icon, GTK_ALIGN_START);
+  gtk_widget_set_margin_start (icon, 12);
+  gtk_widget_set_margin_end (icon, 12);
+  gtk_widget_set_margin_top (icon, 12);
+  gtk_widget_set_margin_bottom (icon, 12);
+
+  /* Right */
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
+
+  /* Right - 1. */
+  label = gtk_label_new (NULL);
+  markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
+  gtk_label_set_markup (GTK_LABEL (label), markup);
+  gtk_label_set_wrap (GTK_LABEL (label), TRUE);
+  gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
+  g_free (markup);
+
+  /* Packing */
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+G_GNUC_END_IGNORE_DEPRECATIONS
+  gtk_box_append (GTK_BOX (content_area), main_box);
+
+  gtk_box_append (GTK_BOX (main_box), icon);
+  gtk_box_append (GTK_BOX (main_box), vbox);
+
+  gtk_box_append (GTK_BOX (vbox), label);
+
+  /* Right - 2. */
+  for (i = 0; i < length; i++)
+    {
+      priv->auth_info[i] = g_strdup (ai_default[i]);
+      if (ai_display[i] != NULL)
+        {
+          box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+          gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
+          gtk_widget_set_margin_top (box, 6);
+          gtk_widget_set_margin_bottom (box, 6);
+
+          label = gtk_label_new (ai_display[i]);
+          gtk_widget_set_halign (label, GTK_ALIGN_START);
+          gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+
+          entry = gtk_entry_new ();
+          focus = entry;
+
+          if (ai_default[i] != NULL)
+            gtk_editable_set_text (GTK_EDITABLE (entry), ai_default[i]);
+
+          gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
+          gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+
+          gtk_box_append (GTK_BOX (vbox), box);
+
+          gtk_box_append (GTK_BOX (box), label);
+          gtk_box_append (GTK_BOX (box), entry);
+
+          g_signal_connect (entry, "changed",
+                            G_CALLBACK (store_entry), &(priv->auth_info[i]));
+        }
+    }
+
+  if (can_store_auth_info)
+    {
+      chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
+      gtk_widget_set_margin_top (chkbtn, 6);
+      gtk_widget_set_margin_bottom (chkbtn, 6);
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (chkbtn), FALSE);
+      gtk_box_append (GTK_BOX (vbox), chkbtn);
+      g_signal_connect (chkbtn, "toggled",
+                        G_CALLBACK (store_auth_info_toggled),
+                        &(priv->store_auth_info));
+    }
+
+  if (focus != NULL)
+    {
+      gtk_widget_grab_focus (focus);
+      focus = NULL;
+    }
+
+  g_object_ref (backend);
+  g_signal_connect (G_OBJECT (dialog), "response",
+                    G_CALLBACK (password_dialog_response), backend);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+gtk_print_backend_destroy (GtkPrintBackend *backend)
+{
+  /* The lifecycle of print backends and printers are tied, such that
+   * the backend owns the printers, but the printers also ref the backend.
+   * This is so that if the app has a reference to a printer its backend
+   * will be around. However, this results in a cycle, which we break
+   * with this call, which causes the print backend to release its printers.
+   */
+  g_object_run_dispose (G_OBJECT (backend));
+}
diff --git a/gtk/print/gtkprintbackendprivate.h b/gtk/print/gtkprintbackendprivate.h
new file mode 100644 (file)
index 0000000..0e72f47
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <gtk/gtk.h>
+#include "gtkunixprint.h"
+#include "gtkprinteroptionsetprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkPrintBackendClass    GtkPrintBackendClass;
+typedef struct _GtkPrintBackendPrivate  GtkPrintBackendPrivate;
+
+#define GTK_PRINT_BACKEND_ERROR (gtk_print_backend_error_quark ())
+
+typedef enum
+{
+  /* TODO: add specific errors */
+  GTK_PRINT_BACKEND_ERROR_GENERIC
+} GtkPrintBackendError;
+
+GDK_AVAILABLE_IN_ALL
+GQuark     gtk_print_backend_error_quark      (void);
+
+#define GTK_TYPE_PRINT_BACKEND                  (gtk_print_backend_get_type ())
+#define GTK_PRINT_BACKEND(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackend))
+#define GTK_PRINT_BACKEND_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+#define GTK_IS_PRINT_BACKEND(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_BACKEND))
+#define GTK_IS_PRINT_BACKEND_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND))
+#define GTK_PRINT_BACKEND_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendClass))
+
+typedef enum 
+{
+  GTK_PRINT_BACKEND_STATUS_UNKNOWN,
+  GTK_PRINT_BACKEND_STATUS_OK,
+  GTK_PRINT_BACKEND_STATUS_UNAVAILABLE
+} GtkPrintBackendStatus;
+
+struct _GtkPrintBackend
+{
+  GObject parent_instance;
+
+  GtkPrintBackendPrivate *priv;
+};
+
+struct _GtkPrintBackendClass
+{
+  GObjectClass parent_class;
+
+  /* Global backend methods: */
+  void                   (*request_printer_list)            (GtkPrintBackend        *backend);
+  void                   (*print_stream)                    (GtkPrintBackend        *backend,
+                                                            GtkPrintJob            *job,
+                                                            GIOChannel             *data_io,
+                                                            GtkPrintJobCompleteFunc callback,
+                                                            gpointer                user_data,
+                                                            GDestroyNotify          dnotify);
+
+  /* Printer methods: */
+  void                  (*printer_request_details)           (GtkPrinter          *printer);
+  cairo_surface_t *     (*printer_create_cairo_surface)      (GtkPrinter          *printer,
+                                                             GtkPrintSettings    *settings,
+                                                             double               height,
+                                                             double               width,
+                                                             GIOChannel          *cache_io);
+  GtkPrinterOptionSet * (*printer_get_options)               (GtkPrinter          *printer,
+                                                             GtkPrintSettings    *settings,
+                                                             GtkPageSetup        *page_setup,
+                                                             GtkPrintCapabilities capabilities);
+  gboolean              (*printer_mark_conflicts)            (GtkPrinter          *printer,
+                                                             GtkPrinterOptionSet *options);
+  void                  (*printer_get_settings_from_options) (GtkPrinter          *printer,
+                                                             GtkPrinterOptionSet *options,
+                                                             GtkPrintSettings    *settings);
+  void                  (*printer_prepare_for_print)         (GtkPrinter          *printer,
+                                                             GtkPrintJob         *print_job,
+                                                             GtkPrintSettings    *settings,
+                                                             GtkPageSetup        *page_setup);
+  GList  *              (*printer_list_papers)               (GtkPrinter          *printer);
+  GtkPageSetup *        (*printer_get_default_page_size)     (GtkPrinter          *printer);
+  gboolean              (*printer_get_hard_margins)          (GtkPrinter          *printer,
+                                                             double              *top,
+                                                             double              *bottom,
+                                                             double              *left,
+                                                             double              *right);
+  GtkPrintCapabilities  (*printer_get_capabilities)          (GtkPrinter          *printer);
+
+  /* Signals */
+  void                  (*printer_list_changed)              (GtkPrintBackend     *backend);
+  void                  (*printer_list_done)                 (GtkPrintBackend     *backend);
+  void                  (*printer_added)                     (GtkPrintBackend     *backend,
+                                                             GtkPrinter          *printer);
+  void                  (*printer_removed)                   (GtkPrintBackend     *backend,
+                                                             GtkPrinter          *printer);
+  void                  (*printer_status_changed)            (GtkPrintBackend     *backend,
+                                                             GtkPrinter          *printer);
+  void                  (*request_password)                  (GtkPrintBackend     *backend,
+                                                              gpointer             auth_info_required,
+                                                              gpointer             auth_info_default,
+                                                              gpointer             auth_info_display,
+                                                              gpointer             auth_info_visible,
+                                                              const char          *prompt,
+                                                              gboolean             can_store_auth_info);
+
+  /* not a signal */
+  void                  (*set_password)                      (GtkPrintBackend     *backend,
+                                                              char               **auth_info_required,
+                                                              char               **auth_info,
+                                                              gboolean             store_auth_info);
+
+  gboolean              (*printer_get_hard_margins_for_paper_size) (GtkPrinter    *printer,
+                                                                   GtkPaperSize  *paper_size,
+                                                                   double        *top,
+                                                                   double        *bottom,
+                                                                   double        *left,
+                                                                   double        *right);
+};
+
+#define GTK_PRINT_BACKEND_EXTENSION_POINT_NAME "gtk-print-backend"
+
+GDK_AVAILABLE_IN_ALL
+GType   gtk_print_backend_get_type       (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GList      *gtk_print_backend_get_printer_list     (GtkPrintBackend         *print_backend);
+GDK_AVAILABLE_IN_ALL
+GListModel *gtk_print_backend_get_printers         (GtkPrintBackend         *print_backend);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_print_backend_printer_list_is_done (GtkPrintBackend         *print_backend);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter *gtk_print_backend_find_printer         (GtkPrintBackend         *print_backend,
+                                                   const char              *printer_name);
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_print_stream         (GtkPrintBackend         *print_backend,
+                                                   GtkPrintJob             *job,
+                                                   GIOChannel              *data_io,
+                                                   GtkPrintJobCompleteFunc  callback,
+                                                   gpointer                 user_data,
+                                                   GDestroyNotify           dnotify);
+GDK_AVAILABLE_IN_ALL
+GList *     gtk_print_backend_load_modules         (void);
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_destroy              (GtkPrintBackend         *print_backend);
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_set_password         (GtkPrintBackend         *backend, 
+                                                    char                   **auth_info_required,
+                                                    char                   **auth_info,
+                                                    gboolean                 can_store_auth_info);
+
+/* Backend-only functions for GtkPrintBackend */
+
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_add_printer          (GtkPrintBackend         *print_backend,
+                                                   GtkPrinter              *printer);
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_remove_printer       (GtkPrintBackend         *print_backend,
+                                                   GtkPrinter              *printer);
+GDK_AVAILABLE_IN_ALL
+void        gtk_print_backend_set_list_done        (GtkPrintBackend         *backend);
+
+
+/* Backend-only functions for GtkPrinter */
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_is_new                (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_accepts_pdf       (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_accepts_ps        (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_is_new            (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_is_active         (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_is_paused         (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_is_accepting_jobs (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_has_details       (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_is_default        (GtkPrinter      *printer,
+                                              gboolean         val);
+GDK_AVAILABLE_IN_ALL
+void        gtk_printer_set_icon_name         (GtkPrinter      *printer,
+                                              const char      *icon);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_job_count         (GtkPrinter      *printer,
+                                              int              count);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_location          (GtkPrinter      *printer,
+                                              const char      *location);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_description       (GtkPrinter      *printer,
+                                              const char      *description);
+GDK_AVAILABLE_IN_ALL
+gboolean    gtk_printer_set_state_message     (GtkPrinter      *printer,
+                                              const char      *message);
+
+void        gtk_print_backends_init (void);
+
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprinter.c b/gtk/print/gtkprinter.c
new file mode 100644 (file)
index 0000000..9b16d02
--- /dev/null
@@ -0,0 +1,1368 @@
+/* GtkPrinter
+ * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "gtkprivate.h"
+
+#include "gtkprinter.h"
+#include "gtkprinterprivate.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprintjob.h"
+
+/**
+ * GtkPrinter:
+ *
+ * A `GtkPrinter` object represents a printer.
+ *
+ * You only need to deal directly with printers if you use the
+ * non-portable [class@Gtk.PrintUnixDialog] API.
+ *
+ * A `GtkPrinter` allows to get status information about the printer,
+ * such as its description, its location, the number of queued jobs,
+ * etc. Most importantly, a `GtkPrinter` object can be used to create
+ * a [class@Gtk.PrintJob] object, which lets you print to the printer.
+ */
+
+
+static void gtk_printer_finalize     (GObject *object);
+
+struct _GtkPrinterPrivate
+{
+  char *name;
+  char *location;
+  char *description;
+  char *icon_name;
+
+  guint is_active         : 1;
+  guint is_paused         : 1;
+  guint is_accepting_jobs : 1;
+  guint is_new            : 1;
+  guint is_virtual        : 1;
+  guint is_default        : 1;
+  guint has_details       : 1;
+  guint accepts_pdf       : 1;
+  guint accepts_ps        : 1;
+
+  char *state_message;
+  int job_count;
+
+  GtkPrintBackend *backend;
+};
+
+enum {
+  DETAILS_ACQUIRED,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+  PROP_NAME,
+  PROP_BACKEND,
+  PROP_IS_VIRTUAL,
+  PROP_STATE_MESSAGE,
+  PROP_LOCATION,
+  PROP_ICON_NAME,
+  PROP_JOB_COUNT,
+  PROP_ACCEPTS_PDF,
+  PROP_ACCEPTS_PS,
+  PROP_PAUSED,
+  PROP_ACCEPTING_JOBS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gtk_printer_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec);
+static void gtk_printer_get_property (GObject      *object,
+                                     guint         prop_id,
+                                     GValue       *value,
+                                     GParamSpec   *pspec);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinter, gtk_printer, G_TYPE_OBJECT)
+
+static void
+gtk_printer_class_init (GtkPrinterClass *class)
+{
+  GObjectClass *object_class;
+  object_class = (GObjectClass *) class;
+
+  object_class->finalize = gtk_printer_finalize;
+
+  object_class->set_property = gtk_printer_set_property;
+  object_class->get_property = gtk_printer_get_property;
+
+  /**
+   * GtkPrinter:name: (attributes org.gtk.Property.get=gtk_printer_get_name)
+   *
+   * The name of the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_NAME,
+                                   g_param_spec_string ("name", NULL, NULL,
+                                                       "",
+                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrinter:backend: (attributes org.gtk.Property.get=gtk_printer_get_backend)
+   *
+   * The backend for the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_BACKEND,
+                                   g_param_spec_object ("backend", NULL, NULL,
+                                                       GTK_TYPE_PRINT_BACKEND,
+                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrinter:is-virtual: (attributes org.gtk.Property.get=gtk_printer_is_virtual)
+   *
+   * %FALSE if this represents a real hardware device.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_IS_VIRTUAL,
+                                   g_param_spec_boolean ("is-virtual", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrinter:accepts-pdf: (attributes org.gtk.Property.get=gtk_printer_accepts_pdf)
+   *
+   * %TRUE if this printer can accept PDF.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_ACCEPTS_PDF,
+                                   g_param_spec_boolean ("accepts-pdf", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrinter:accepts-ps: (attributes org.gtk.Property.get=gtk_printer_accepts_ps)
+   *
+   * %TRUE if this printer can accept PostScript.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_ACCEPTS_PS,
+                                   g_param_spec_boolean ("accepts-ps", NULL, NULL,
+                                                        TRUE,
+                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrinter:state-message: (attributes org.gtk.Property.get=gtk_printer_get_state_message)
+   *
+   * String giving the current status of the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_STATE_MESSAGE,
+                                   g_param_spec_string ("state-message", NULL, NULL,
+                                                       "",
+                                                       GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter:location: (attributes org.gtk.Property.get=gtk_printer_get_location)
+   *
+   * Information about the location of the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_LOCATION,
+                                   g_param_spec_string ("location", NULL, NULL,
+                                                       "",
+                                                       GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter:icon-name: (attributes org.gtk.Property.get=gtk_printer_get_icon_name)
+   *
+   * Icon name to use for the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_ICON_NAME,
+                                   g_param_spec_string ("icon-name", NULL, NULL,
+                                                       "printer",
+                                                       GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter:job-count: (attributes org.gtk.Property.get=gtk_printer_get_job_count)
+   *
+   * Number of jobs queued in the printer.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_JOB_COUNT,
+                                  g_param_spec_int ("job-count", NULL, NULL,
+                                                    0,
+                                                    G_MAXINT,
+                                                    0,
+                                                    GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter:paused: (attributes org.gtk.Property.get=gtk_printer_is_paused)
+   *
+   * %TRUE if this printer is paused.
+   *
+   * A paused printer still accepts jobs, but it does
+   * not print them.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_PAUSED,
+                                   g_param_spec_boolean ("paused", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter:accepting-jobs: (attributes org.gtk.Property.get=gtk_printer_is_accepting_jobs)
+   *
+   * %TRUE if the printer is accepting jobs.
+   */
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_ACCEPTING_JOBS,
+                                   g_param_spec_boolean ("accepting-jobs", NULL, NULL,
+                                                        TRUE,
+                                                        GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrinter::details-acquired:
+   * @printer: the `GtkPrinter` on which the signal is emitted
+   * @success: %TRUE if the details were successfully acquired
+   *
+   * Emitted in response to a request for detailed information
+   * about a printer from the print backend.
+   *
+   * The @success parameter indicates if the information was
+   * actually obtained.
+   */
+  signals[DETAILS_ACQUIRED] =
+    g_signal_new (I_("details-acquired"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrinterClass, details_acquired),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+gtk_printer_init (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  priv->name = NULL;
+  priv->location = NULL;
+  priv->description = NULL;
+  priv->icon_name = g_strdup ("printer");
+
+  priv->is_active = TRUE;
+  priv->is_paused = FALSE;
+  priv->is_accepting_jobs = TRUE;
+  priv->is_new = TRUE;
+  priv->has_details = FALSE;
+  priv->accepts_pdf = FALSE;
+  priv->accepts_ps = TRUE;
+
+  priv->state_message = NULL;  
+  priv->job_count = 0;
+}
+
+static void
+gtk_printer_finalize (GObject *object)
+{
+  GtkPrinter *printer = GTK_PRINTER (object);
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_free (priv->name);
+  g_free (priv->location);
+  g_free (priv->description);
+  g_free (priv->state_message);
+  g_free (priv->icon_name);
+
+  if (priv->backend)
+    g_object_unref (priv->backend);
+
+  G_OBJECT_CLASS (gtk_printer_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_set_property (GObject         *object,
+                         guint            prop_id,
+                         const GValue    *value,
+                         GParamSpec      *pspec)
+{
+  GtkPrinter *printer = GTK_PRINTER (object);
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      priv->name = g_value_dup_string (value);
+      break;
+    
+    case PROP_BACKEND:
+      priv->backend = GTK_PRINT_BACKEND (g_value_dup_object (value));
+      break;
+
+    case PROP_IS_VIRTUAL:
+      priv->is_virtual = g_value_get_boolean (value);
+      break;
+
+    case PROP_ACCEPTS_PDF:
+      priv->accepts_pdf = g_value_get_boolean (value);
+      break;
+
+    case PROP_ACCEPTS_PS:
+      priv->accepts_ps = g_value_get_boolean (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_printer_get_property (GObject    *object,
+                         guint       prop_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+  GtkPrinter *printer = GTK_PRINTER (object);
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      if (priv->name)
+       g_value_set_string (value, priv->name);
+      else
+       g_value_set_static_string (value, "");
+      break;
+    case PROP_BACKEND:
+      g_value_set_object (value, priv->backend);
+      break;
+    case PROP_STATE_MESSAGE:
+      if (priv->state_message)
+       g_value_set_string (value, priv->state_message);
+      else
+       g_value_set_static_string (value, "");
+      break;
+    case PROP_LOCATION:
+      if (priv->location)
+       g_value_set_string (value, priv->location);
+      else
+       g_value_set_static_string (value, "");
+      break;
+    case PROP_ICON_NAME:
+      if (priv->icon_name)
+       g_value_set_string (value, priv->icon_name);
+      else
+       g_value_set_static_string (value, "printer");
+      break;
+    case PROP_JOB_COUNT:
+      g_value_set_int (value, priv->job_count);
+      break;
+    case PROP_IS_VIRTUAL:
+      g_value_set_boolean (value, priv->is_virtual);
+      break;
+    case PROP_ACCEPTS_PDF:
+      g_value_set_boolean (value, priv->accepts_pdf);
+      break;
+    case PROP_ACCEPTS_PS:
+      g_value_set_boolean (value, priv->accepts_ps);
+      break;
+    case PROP_PAUSED:
+      g_value_set_boolean (value, priv->is_paused);
+      break;
+    case PROP_ACCEPTING_JOBS:
+      g_value_set_boolean (value, priv->is_accepting_jobs);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_printer_new:
+ * @name: the name of the printer
+ * @backend: a `GtkPrintBackend`
+ * @virtual_: whether the printer is virtual
+ *
+ * Creates a new `GtkPrinter`.
+ *
+ * Returns: a new `GtkPrinter`
+ */
+GtkPrinter *
+gtk_printer_new (const char      *name,
+                GtkPrintBackend *backend,
+                gboolean         virtual_)
+{
+  GObject *result;
+  
+  result = g_object_new (GTK_TYPE_PRINTER,
+                        "name", name,
+                        "backend", backend,
+                        "is-virtual", virtual_,
+                         NULL);
+
+  return (GtkPrinter *) result;
+}
+
+/**
+ * gtk_printer_get_backend: (attributes org.gtk.Method.get_property=backend)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the backend of the printer.
+ *
+ * Returns: (transfer none): the backend of @printer
+ */
+GtkPrintBackend *
+gtk_printer_get_backend (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+  
+  return priv->backend;
+}
+
+/**
+ * gtk_printer_get_name: (attributes org.gtk.Method.get_property=name)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the name of the printer.
+ *
+ * Returns: the name of @printer
+ */
+const char *
+gtk_printer_get_name (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  return priv->name;
+}
+
+/**
+ * gtk_printer_get_description:
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the description of the printer.
+ *
+ * Returns: the description of @printer
+ */
+const char *
+gtk_printer_get_description (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+  
+  return priv->description;
+}
+
+gboolean
+gtk_printer_set_description (GtkPrinter  *printer,
+                            const char *description)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (g_strcmp0 (priv->description, description) == 0)
+    return FALSE;
+
+  g_free (priv->description);
+  priv->description = g_strdup (description);
+  
+  return TRUE;
+}
+
+/**
+ * gtk_printer_get_state_message: (attributes org.gtk.Method.get_property=state-message)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns the state message describing the current state
+ * of the printer.
+ *
+ * Returns: the state message of @printer
+ */
+const char *
+gtk_printer_get_state_message (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  return priv->state_message;
+}
+
+gboolean
+gtk_printer_set_state_message (GtkPrinter  *printer,
+                              const char *message)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (g_strcmp0 (priv->state_message, message) == 0)
+    return FALSE;
+
+  g_free (priv->state_message);
+  priv->state_message = g_strdup (message);
+  g_object_notify (G_OBJECT (printer), "state-message");
+
+  return TRUE;
+}
+
+/**
+ * gtk_printer_get_location: (attributes org.gtk.Method.get_property=location)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns a description of the location of the printer.
+ *
+ * Returns: the location of @printer
+ */
+const char *
+gtk_printer_get_location (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  return priv->location;
+}
+
+gboolean
+gtk_printer_set_location (GtkPrinter  *printer,
+                         const char *location)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (g_strcmp0 (priv->location, location) == 0)
+    return FALSE;
+
+  g_free (priv->location);
+  priv->location = g_strdup (location);
+  g_object_notify (G_OBJECT (printer), "location");
+  
+  return TRUE;
+}
+
+/**
+ * gtk_printer_get_icon_name: (attributes org.gtk.Method.get_property=icon-name)
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the name of the icon to use for the printer.
+ *
+ * Returns: the icon name for @printer
+ */
+const char *
+gtk_printer_get_icon_name (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  return priv->icon_name;
+}
+
+void
+gtk_printer_set_icon_name (GtkPrinter  *printer,
+                          const char *icon)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  g_free (priv->icon_name);
+  priv->icon_name = g_strdup (icon);
+  g_object_notify (G_OBJECT (printer), "icon-name");
+}
+
+/**
+ * gtk_printer_get_job_count: (attributes org.gtk.Method.get_property=job-count)
+ * @printer: a `GtkPrinter`
+ *
+ * Gets the number of jobs currently queued on the printer.
+ *
+ * Returns: the number of jobs on @printer
+ */
+int
+gtk_printer_get_job_count (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
+
+  return priv->job_count;
+}
+
+gboolean
+gtk_printer_set_job_count (GtkPrinter *printer,
+                          int         count)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (priv->job_count == count)
+    return FALSE;
+
+  priv->job_count = count;
+  
+  g_object_notify (G_OBJECT (printer), "job-count");
+  
+  return TRUE;
+}
+
+/**
+ * gtk_printer_has_details:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer details are available.
+ *
+ * Returns: %TRUE if @printer details are available
+ */
+gboolean
+gtk_printer_has_details (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  return priv->has_details;
+}
+
+void
+gtk_printer_set_has_details (GtkPrinter *printer,
+                            gboolean    val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  priv->has_details = val;
+}
+
+/**
+ * gtk_printer_is_active:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is currently active (i.e.
+ * accepts new jobs).
+ *
+ * Returns: %TRUE if @printer is active
+ */
+gboolean
+gtk_printer_is_active (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->is_active;
+}
+
+void
+gtk_printer_set_is_active (GtkPrinter *printer,
+                          gboolean val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  priv->is_active = val;
+}
+
+/**
+ * gtk_printer_is_paused: (attributes org.gtk.Method.get_property=paused)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is currently paused.
+ *
+ * A paused printer still accepts jobs, but it is not
+ * printing them.
+ *
+ * Returns: %TRUE if @printer is paused
+ */
+gboolean
+gtk_printer_is_paused (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->is_paused;
+}
+
+gboolean
+gtk_printer_set_is_paused (GtkPrinter *printer,
+                          gboolean    val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (val == priv->is_paused)
+    return FALSE;
+
+  priv->is_paused = val;
+
+  return TRUE;
+}
+
+/**
+ * gtk_printer_is_accepting_jobs: (attributes org.gtk.Method.get_property=accepting-jobs)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is accepting jobs
+ *
+ * Returns: %TRUE if @printer is accepting jobs
+ */
+gboolean
+gtk_printer_is_accepting_jobs (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->is_accepting_jobs;
+}
+
+gboolean
+gtk_printer_set_is_accepting_jobs (GtkPrinter *printer,
+                                  gboolean val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+
+  if (val == priv->is_accepting_jobs)
+    return FALSE;
+
+  priv->is_accepting_jobs = val;
+
+  return TRUE;
+}
+
+/**
+ * gtk_printer_is_virtual: (attributes org.gtk.Method.get_property=is-virtual)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is virtual (i.e. does not
+ * represent actual printer hardware, but something like
+ * a CUPS class).
+ *
+ * Returns: %TRUE if @printer is virtual
+ */
+gboolean
+gtk_printer_is_virtual (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->is_virtual;
+}
+
+/**
+ * gtk_printer_accepts_pdf: (attributes org.gtk.Method.get_property=accepts-pdf)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer accepts input in
+ * PDF format.
+ *
+ * Returns: %TRUE if @printer accepts PDF
+ */
+gboolean
+gtk_printer_accepts_pdf (GtkPrinter *printer)
+{ 
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->accepts_pdf;
+}
+
+void
+gtk_printer_set_accepts_pdf (GtkPrinter *printer,
+                            gboolean val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  priv->accepts_pdf = val;
+}
+
+/**
+ * gtk_printer_accepts_ps: (attributes org.gtk.Method.get_property=accepts-ps)
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer accepts input in
+ * PostScript format.
+ *
+ * Returns: %TRUE if @printer accepts PostScript
+ */
+gboolean
+gtk_printer_accepts_ps (GtkPrinter *printer)
+{ 
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), TRUE);
+  
+  return priv->accepts_ps;
+}
+
+void
+gtk_printer_set_accepts_ps (GtkPrinter *printer,
+                           gboolean val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  priv->accepts_ps = val;
+}
+
+gboolean
+gtk_printer_is_new (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+  
+  return priv->is_new;
+}
+
+void
+gtk_printer_set_is_new (GtkPrinter *printer,
+                       gboolean val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  priv->is_new = val;
+}
+
+
+/**
+ * gtk_printer_is_default:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns whether the printer is the default printer.
+ *
+ * Returns: %TRUE if @printer is the default
+ */
+gboolean
+gtk_printer_is_default (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), FALSE);
+  
+  return priv->is_default;
+}
+
+void
+gtk_printer_set_is_default (GtkPrinter *printer,
+                           gboolean    val)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  priv->is_default = val;
+}
+
+/**
+ * gtk_printer_request_details:
+ * @printer: a `GtkPrinter`
+ *
+ * Requests the printer details.
+ *
+ * When the details are available, the
+ * [signal@Gtk.Printer::details-acquired] signal
+ * will be emitted on @printer.
+ */
+void
+gtk_printer_request_details (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class;
+
+  g_return_if_fail (GTK_IS_PRINTER (printer));
+
+  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+  backend_class->printer_request_details (printer);
+}
+
+GtkPrinterOptionSet *
+_gtk_printer_get_options (GtkPrinter           *printer,
+                         GtkPrintSettings     *settings,
+                         GtkPageSetup         *page_setup,
+                         GtkPrintCapabilities  capabilities)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_get_options (printer, settings, page_setup, capabilities);
+}
+
+gboolean
+_gtk_printer_mark_conflicts (GtkPrinter          *printer,
+                            GtkPrinterOptionSet *options)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_mark_conflicts (printer, options);
+}
+  
+void
+_gtk_printer_get_settings_from_options (GtkPrinter          *printer,
+                                       GtkPrinterOptionSet *options,
+                                       GtkPrintSettings    *settings)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  backend_class->printer_get_settings_from_options (printer, options, settings);
+}
+
+void
+_gtk_printer_prepare_for_print (GtkPrinter       *printer,
+                               GtkPrintJob      *print_job,
+                               GtkPrintSettings *settings,
+                               GtkPageSetup     *page_setup)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  backend_class->printer_prepare_for_print (printer, print_job, settings, page_setup);
+}
+
+cairo_surface_t *
+_gtk_printer_create_cairo_surface (GtkPrinter       *printer,
+                                  GtkPrintSettings *settings,
+                                  double            width, 
+                                  double            height,
+                                  GIOChannel       *cache_io)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_create_cairo_surface (printer, settings,
+                                                     width, height, cache_io);
+}
+
+/**
+ * gtk_printer_list_papers:
+ * @printer: a `GtkPrinter`
+ *
+ * Lists all the paper sizes @printer supports.
+ *
+ * This will return and empty list unless the printer’s details
+ * are available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: (element-type GtkPageSetup) (transfer full): a newly
+ *   allocated list of newly allocated `GtkPageSetup`s.
+ */
+GList  *
+gtk_printer_list_papers (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class;
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+  return backend_class->printer_list_papers (printer);
+}
+
+/**
+ * gtk_printer_get_default_page_size:
+ * @printer: a `GtkPrinter`
+ *
+ * Returns default page size of @printer.
+ *
+ * Returns: (transfer full): a newly allocated `GtkPageSetup` with default page size
+ *   of the printer.
+ */
+GtkPageSetup *
+gtk_printer_get_default_page_size (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class;
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), NULL);
+
+  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_get_default_page_size (printer);
+}
+
+/**
+ * gtk_printer_get_hard_margins:
+ * @printer: a `GtkPrinter`
+ * @top: (out): a location to store the top margin in
+ * @bottom: (out): a location to store the bottom margin in
+ * @left: (out): a location to store the left margin in
+ * @right: (out): a location to store the right margin in
+ *
+ * Retrieve the hard margins of @printer.
+ *
+ * These are the margins that define the area at the borders
+ * of the paper that the printer cannot print to.
+ *
+ * Note: This will not succeed unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: %TRUE iff the hard margins were retrieved
+ */
+gboolean
+gtk_printer_get_hard_margins (GtkPrinter *printer,
+                             double     *top,
+                             double     *bottom,
+                             double     *left,
+                             double     *right)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_get_hard_margins (printer, top, bottom, left, right);
+}
+
+/**
+ * gtk_printer_get_hard_margins_for_paper_size:
+ * @printer: a `GtkPrinter`
+ * @paper_size: a `GtkPaperSize`
+ * @top: (out): a location to store the top margin in
+ * @bottom: (out): a location to store the bottom margin in
+ * @left: (out): a location to store the left margin in
+ * @right: (out): a location to store the right margin in
+ *
+ * Retrieve the hard margins of @printer for @paper_size.
+ *
+ * These are the margins that define the area at the borders
+ * of the paper that the printer cannot print to.
+ *
+ * Note: This will not succeed unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Return value: %TRUE iff the hard margins were retrieved
+ */
+gboolean
+gtk_printer_get_hard_margins_for_paper_size (GtkPrinter   *printer,
+                                            GtkPaperSize *paper_size,
+                                            double       *top,
+                                            double       *bottom,
+                                            double       *left,
+                                            double       *right)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+
+  return backend_class->printer_get_hard_margins_for_paper_size (printer, paper_size, top, bottom, left, right);
+}
+
+/**
+ * gtk_printer_get_capabilities:
+ * @printer: a `GtkPrinter`
+ * 
+ * Returns the printer’s capabilities.
+ *
+ * This is useful when you’re using `GtkPrintUnixDialog`’s
+ * manual-capabilities setting and need to know which settings
+ * the printer can handle and which you must handle yourself.
+ *
+ * This will return 0 unless the printer’s details are
+ * available, see [method@Gtk.Printer.has_details] and
+ * [method@Gtk.Printer.request_details].
+ *
+ * Returns: the printer’s capabilities
+ */
+GtkPrintCapabilities
+gtk_printer_get_capabilities (GtkPrinter *printer)
+{
+  GtkPrinterPrivate *priv = gtk_printer_get_instance_private (printer);
+  GtkPrintBackendClass *backend_class;
+
+  g_return_val_if_fail (GTK_IS_PRINTER (printer), 0);
+
+  backend_class = GTK_PRINT_BACKEND_GET_CLASS (priv->backend);
+  return backend_class->printer_get_capabilities (printer);
+}
+
+/**
+ * gtk_printer_compare:
+ * @a: a `GtkPrinter`
+ * @b: another `GtkPrinter`
+ *
+ * Compares two printers.
+ *
+ * Returns: 0 if the printer match, a negative value if @a < @b,
+ *   or a positive value if @a > @b
+ */
+int
+gtk_printer_compare (GtkPrinter *a, 
+                     GtkPrinter *b)
+{
+  const char *name_a, *name_b;
+  
+  g_assert (GTK_IS_PRINTER (a) && GTK_IS_PRINTER (b));
+  
+  name_a = gtk_printer_get_name (a);
+  name_b = gtk_printer_get_name (b);
+  if (name_a == NULL  && name_b == NULL)
+    return 0;
+  else if (name_a == NULL)
+    return G_MAXINT;
+  else if (name_b == NULL)
+    return G_MININT;
+  else
+    return g_ascii_strcasecmp (name_a, name_b);
+}
+
+
+typedef struct 
+{
+  GList *backends;
+  GtkPrinterFunc func;
+  gpointer data;
+  GDestroyNotify destroy;
+  GMainLoop *loop;
+} PrinterList;
+
+static void list_done_cb (GtkPrintBackend *backend, 
+                         PrinterList     *printer_list);
+
+static void
+stop_enumeration (PrinterList *printer_list)
+{
+  GList *list, *next;
+  GtkPrintBackend *backend;
+
+  for (list = printer_list->backends; list; list = next)
+    {
+      next = list->next;
+      backend = GTK_PRINT_BACKEND (list->data);
+      list_done_cb (backend, printer_list);
+    }
+}
+
+static void 
+free_printer_list (PrinterList *printer_list)
+{
+  if (printer_list->destroy)
+    printer_list->destroy (printer_list->data);
+
+  if (printer_list->loop)
+    {    
+      g_main_loop_quit (printer_list->loop);
+      g_main_loop_unref (printer_list->loop);
+    }
+
+  g_free (printer_list);
+}
+
+static gboolean
+list_added_cb (GtkPrintBackend *backend, 
+              GtkPrinter      *printer, 
+              PrinterList     *printer_list)
+{
+  if (printer_list->func (printer, printer_list->data))
+    {
+      stop_enumeration (printer_list);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+backend_status_changed (GObject    *object,
+                        GParamSpec *pspec,
+                        gpointer    data)
+{
+  GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
+  PrinterList *printer_list = data;
+  GtkPrintBackendStatus status;
+
+  g_object_get (backend, "status", &status, NULL);
+  if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE)
+    list_done_cb (backend, printer_list);  
+}
+
+static gboolean
+list_printers_remove_backend (PrinterList     *printer_list,
+                              GtkPrintBackend *backend)
+{
+  printer_list->backends = g_list_remove (printer_list->backends, backend);
+  gtk_print_backend_destroy (backend);
+  g_object_unref (backend);
+
+  if (printer_list->backends == NULL)
+    {
+      free_printer_list (printer_list);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+list_done_cb (GtkPrintBackend *backend,
+             PrinterList     *printer_list)
+{
+  g_signal_handlers_disconnect_by_func (backend, list_added_cb, printer_list);
+  g_signal_handlers_disconnect_by_func (backend, list_done_cb, printer_list);
+  g_signal_handlers_disconnect_by_func (backend, backend_status_changed, printer_list);
+
+  list_printers_remove_backend(printer_list, backend);
+}
+
+static gboolean
+list_printers_init (PrinterList     *printer_list,
+                   GtkPrintBackend *backend)
+{
+  GList *list, *node;
+  GtkPrintBackendStatus status;
+
+  list = gtk_print_backend_get_printer_list (backend);
+
+  for (node = list; node != NULL; node = node->next)
+    {
+      if (list_added_cb (backend, node->data, printer_list))
+        {
+          g_list_free (list);
+          return TRUE;
+        }
+    }
+
+  g_list_free (list);
+
+  g_object_get (backend, "status", &status, NULL);
+  
+  if (status == GTK_PRINT_BACKEND_STATUS_UNAVAILABLE || 
+      gtk_print_backend_printer_list_is_done (backend))
+    {
+      if (list_printers_remove_backend (printer_list, backend))
+        return TRUE;
+    }
+  else
+    {
+      g_signal_connect (backend, "printer-added", 
+                       (GCallback) list_added_cb, 
+                       printer_list);
+      g_signal_connect (backend, "printer-list-done", 
+                       (GCallback) list_done_cb, 
+                       printer_list);
+      g_signal_connect (backend, "notify::status", 
+                        (GCallback) backend_status_changed,
+                        printer_list);     
+    }
+
+  return FALSE;
+}
+
+/**
+ * gtk_enumerate_printers:
+ * @func: a function to call for each printer
+ * @data: user data to pass to @func
+ * @destroy: function to call if @data is no longer needed
+ * @wait: if %TRUE, wait in a recursive mainloop until
+ *    all printers are enumerated; otherwise return early
+ *
+ * Calls a function for all `GtkPrinter`s.
+ *
+ * If @func returns %TRUE, the enumeration is stopped.
+ */
+void
+gtk_enumerate_printers (GtkPrinterFunc func,
+                       gpointer       data,
+                       GDestroyNotify destroy,
+                       gboolean       wait)
+{
+  PrinterList *printer_list;
+  GList *node, *next;
+  GtkPrintBackend *backend;
+
+  printer_list = g_new0 (PrinterList, 1);
+
+  printer_list->func = func;
+  printer_list->data = data;
+  printer_list->destroy = destroy;
+
+  if (g_module_supported ())
+    printer_list->backends = gtk_print_backend_load_modules ();
+  
+  if (printer_list->backends == NULL)
+    {
+      free_printer_list (printer_list);
+      return;
+    }
+
+  for (node = printer_list->backends; node != NULL; node = next)
+    {
+      next = node->next;
+      backend = GTK_PRINT_BACKEND (node->data);
+      if (list_printers_init (printer_list, backend))
+        return;
+    }
+
+  if (wait && printer_list->backends)
+    {
+      printer_list->loop = g_main_loop_new (NULL, FALSE);
+      g_main_loop_run (printer_list->loop);
+    }
+}
+
+GType
+gtk_print_capabilities_get_type (void)
+{
+  static GType etype = 0;
+
+  if (G_UNLIKELY (etype == 0))
+    {
+      static const GFlagsValue values[] = {
+        { GTK_PRINT_CAPABILITY_PAGE_SET, "GTK_PRINT_CAPABILITY_PAGE_SET", "page-set" },
+        { GTK_PRINT_CAPABILITY_COPIES, "GTK_PRINT_CAPABILITY_COPIES", "copies" },
+        { GTK_PRINT_CAPABILITY_COLLATE, "GTK_PRINT_CAPABILITY_COLLATE", "collate" },
+        { GTK_PRINT_CAPABILITY_REVERSE, "GTK_PRINT_CAPABILITY_REVERSE", "reverse" },
+        { GTK_PRINT_CAPABILITY_SCALE, "GTK_PRINT_CAPABILITY_SCALE", "scale" },
+        { GTK_PRINT_CAPABILITY_GENERATE_PDF, "GTK_PRINT_CAPABILITY_GENERATE_PDF", "generate-pdf" },
+        { GTK_PRINT_CAPABILITY_GENERATE_PS, "GTK_PRINT_CAPABILITY_GENERATE_PS", "generate-ps" },
+        { GTK_PRINT_CAPABILITY_PREVIEW, "GTK_PRINT_CAPABILITY_PREVIEW", "preview" },
+       { GTK_PRINT_CAPABILITY_NUMBER_UP, "GTK_PRINT_CAPABILITY_NUMBER_UP", "number-up"},
+        { GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT, "GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT", "number-up-layout" },
+        { 0, NULL, NULL }
+      };
+
+      etype = g_flags_register_static (I_("GtkPrintCapabilities"), values);
+    }
+
+  return etype;
+}
diff --git a/gtk/print/gtkprinter.h b/gtk/print/gtkprinter.h
new file mode 100644 (file)
index 0000000..55e0fe4
--- /dev/null
@@ -0,0 +1,166 @@
+/* GtkPrinter
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_CAPABILITIES (gtk_print_capabilities_get_type ())
+
+/* Note, this type is manually registered with GObject in gtkprinter.c
+ * If you add any flags, update the registration as well!
+ */
+/**
+ * GtkPrintCapabilities:
+ * @GTK_PRINT_CAPABILITY_PAGE_SET: Print dialog will offer printing even/odd pages.
+ * @GTK_PRINT_CAPABILITY_COPIES: Print dialog will allow to print multiple copies.
+ * @GTK_PRINT_CAPABILITY_COLLATE: Print dialog will allow to collate multiple copies.
+ * @GTK_PRINT_CAPABILITY_REVERSE: Print dialog will allow to print pages in reverse order.
+ * @GTK_PRINT_CAPABILITY_SCALE: Print dialog will allow to scale the output.
+ * @GTK_PRINT_CAPABILITY_GENERATE_PDF: The program will send the document to
+ *   the printer in PDF format
+ * @GTK_PRINT_CAPABILITY_GENERATE_PS: The program will send the document to
+ *   the printer in Postscript format
+ * @GTK_PRINT_CAPABILITY_PREVIEW: Print dialog will offer a preview
+ * @GTK_PRINT_CAPABILITY_NUMBER_UP: Print dialog will offer printing multiple
+ *   pages per sheet
+ * @GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT: Print dialog will allow to rearrange
+ *   pages when printing multiple pages per sheet
+ *
+ * Specifies which features the print dialog should offer.
+ *
+ * If neither %GTK_PRINT_CAPABILITY_GENERATE_PDF nor
+ * %GTK_PRINT_CAPABILITY_GENERATE_PS is specified, GTK assumes that all
+ * formats are supported.
+ */
+typedef enum
+{
+  GTK_PRINT_CAPABILITY_PAGE_SET         = 1 << 0,
+  GTK_PRINT_CAPABILITY_COPIES           = 1 << 1,
+  GTK_PRINT_CAPABILITY_COLLATE          = 1 << 2,
+  GTK_PRINT_CAPABILITY_REVERSE          = 1 << 3,
+  GTK_PRINT_CAPABILITY_SCALE            = 1 << 4,
+  GTK_PRINT_CAPABILITY_GENERATE_PDF     = 1 << 5,
+  GTK_PRINT_CAPABILITY_GENERATE_PS      = 1 << 6,
+  GTK_PRINT_CAPABILITY_PREVIEW          = 1 << 7,
+  GTK_PRINT_CAPABILITY_NUMBER_UP        = 1 << 8,
+  GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT = 1 << 9
+} GtkPrintCapabilities;
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_print_capabilities_get_type (void) G_GNUC_CONST;
+
+#define GTK_TYPE_PRINTER                  (gtk_printer_get_type ())
+#define GTK_PRINTER(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER, GtkPrinter))
+#define GTK_IS_PRINTER(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER))
+
+typedef struct _GtkPrinter      GtkPrinter;
+typedef struct _GtkPrintBackend GtkPrintBackend;
+
+GDK_AVAILABLE_IN_ALL
+GType                    gtk_printer_get_type              (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkPrinter              *gtk_printer_new                   (const char      *name,
+                                                           GtkPrintBackend *backend,
+                                                           gboolean         virtual_);
+GDK_AVAILABLE_IN_ALL
+GtkPrintBackend         *gtk_printer_get_backend           (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_printer_get_name              (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_printer_get_state_message     (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_printer_get_description       (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_printer_get_location          (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_printer_get_icon_name         (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+int                      gtk_printer_get_job_count         (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_is_active             (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_is_paused             (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_is_accepting_jobs     (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_is_virtual            (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_is_default            (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_accepts_pdf           (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_accepts_ps            (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+GList                   *gtk_printer_list_papers           (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup            *gtk_printer_get_default_page_size (GtkPrinter      *printer);
+GDK_AVAILABLE_IN_ALL
+int                      gtk_printer_compare               (GtkPrinter *a,
+                                                           GtkPrinter *b);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_has_details           (GtkPrinter       *printer);
+GDK_AVAILABLE_IN_ALL
+void                     gtk_printer_request_details       (GtkPrinter       *printer);
+GDK_AVAILABLE_IN_ALL
+GtkPrintCapabilities     gtk_printer_get_capabilities      (GtkPrinter       *printer);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_get_hard_margins      (GtkPrinter       *printer,
+                                                            double           *top,
+                                                            double           *bottom,
+                                                            double           *left,
+                                                            double           *right);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_printer_get_hard_margins_for_paper_size (GtkPrinter       *printer,
+                                                                     GtkPaperSize     *paper_size,
+                                                                     double           *top,
+                                                                     double           *bottom,
+                                                                     double           *left,
+                                                                     double           *right);
+
+/**
+ * GtkPrinterFunc:
+ * @printer: a `GtkPrinter`
+ * @data: (closure): user data passed to gtk_enumerate_printers()
+ *
+ * The type of function passed to gtk_enumerate_printers().
+ *
+ * Note that you need to ref @printer, if you want to keep
+ * a reference to it after the function has returned.
+ *
+ * Returns: %TRUE to stop the enumeration, %FALSE to continue
+ */
+typedef gboolean (*GtkPrinterFunc) (GtkPrinter *printer,
+                                   gpointer    data);
+
+GDK_AVAILABLE_IN_ALL
+void                     gtk_enumerate_printers        (GtkPrinterFunc   func,
+                                                       gpointer         data,
+                                                       GDestroyNotify   destroy,
+                                                       gboolean         wait);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrinter, g_object_unref)
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprinteroption.c b/gtk/print/gtkprinteroption.c
new file mode 100644 (file)
index 0000000..91e4bde
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <gmodule.h>
+
+#include "gtkprivate.h"
+#include "gtkprinteroptionprivate.h"
+
+/*****************************************
+ *            GtkPrinterOption           *
+ *****************************************/
+
+enum {
+  CHANGED,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+  PROP_VALUE
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void gtk_printer_option_set_property (GObject      *object,
+                                             guint         prop_id,
+                                             const GValue *value,
+                                             GParamSpec   *pspec);
+static void gtk_printer_option_get_property (GObject      *object,
+                                             guint         prop_id,
+                                             GValue       *value,
+                                             GParamSpec   *pspec);
+
+G_DEFINE_TYPE (GtkPrinterOption, gtk_printer_option, G_TYPE_OBJECT)
+
+static void
+gtk_printer_option_finalize (GObject *object)
+{
+  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+  int i;
+  
+  g_free (option->name);
+  g_free (option->display_text);
+  g_free (option->value);
+  for (i = 0; i < option->num_choices; i++)
+    {
+      g_free (option->choices[i]);
+      g_free (option->choices_display[i]);
+    }
+  g_free (option->choices);
+  g_free (option->choices_display);
+  g_free (option->group);
+  
+  G_OBJECT_CLASS (gtk_printer_option_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_init (GtkPrinterOption *option)
+{
+  option->value = g_strdup ("");
+  option->activates_default = FALSE;
+}
+
+static void
+gtk_printer_option_class_init (GtkPrinterOptionClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->finalize = gtk_printer_option_finalize;
+  gobject_class->set_property = gtk_printer_option_set_property;
+  gobject_class->get_property = gtk_printer_option_get_property;
+
+  signals[CHANGED] =
+    g_signal_new (I_("changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrinterOptionClass, changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+
+  g_object_class_install_property (G_OBJECT_CLASS (class),
+                                   PROP_VALUE,
+                                   g_param_spec_string ("value", NULL, NULL,
+                                                        "",
+                                                        GTK_PARAM_READWRITE));
+}
+
+GtkPrinterOption *
+gtk_printer_option_new (const char *name, const char *display_text,
+                       GtkPrinterOptionType type)
+{
+  GtkPrinterOption *option;
+
+  option = g_object_new (GTK_TYPE_PRINTER_OPTION, NULL);
+
+  option->name = g_strdup (name);
+  option->display_text = g_strdup (display_text);
+  option->type = type;
+  
+  return option;
+}
+
+static void
+gtk_printer_option_set_property (GObject         *object,
+                                 guint            prop_id,
+                                 const GValue    *value,
+                                 GParamSpec      *pspec)
+{
+  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_VALUE:
+      gtk_printer_option_set (option, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_printer_option_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GtkPrinterOption *option = GTK_PRINTER_OPTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_VALUE:
+      g_value_set_string (value, option->value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+emit_changed (GtkPrinterOption *option)
+{
+  g_signal_emit (option, signals[CHANGED], 0);
+}
+
+void
+gtk_printer_option_set (GtkPrinterOption *option,
+                       const char *value)
+{
+  if (value == NULL)
+    value = "";
+  
+  if (strcmp (option->value, value) == 0)
+    return;
+
+  if ((option->type == GTK_PRINTER_OPTION_TYPE_PICKONE ||
+       option->type == GTK_PRINTER_OPTION_TYPE_ALTERNATIVE))
+    {
+      int i;
+      
+      for (i = 0; i < option->num_choices; i++)
+       {
+         if (g_ascii_strcasecmp (value, option->choices[i]) == 0)
+           {
+             value = option->choices[i];
+             break;
+           }
+       }
+
+      if (i == option->num_choices)
+       return; /* Not found in available choices */
+    }
+          
+  g_free (option->value);
+  option->value = g_strdup (value);
+  
+  emit_changed (option);
+}
+
+void
+gtk_printer_option_set_boolean (GtkPrinterOption *option,
+                               gboolean value)
+{
+  gtk_printer_option_set (option, value ? "True" : "False");
+}
+
+void
+gtk_printer_option_set_has_conflict  (GtkPrinterOption *option,
+                                     gboolean  has_conflict)
+{
+  has_conflict = has_conflict != 0;
+  
+  if (option->has_conflict == has_conflict)
+    return;
+
+  option->has_conflict = has_conflict;
+  emit_changed (option);
+}
+
+void
+gtk_printer_option_clear_has_conflict (GtkPrinterOption     *option)
+{
+  gtk_printer_option_set_has_conflict  (option, FALSE);
+}
+
+void
+gtk_printer_option_allocate_choices (GtkPrinterOption     *option,
+                                    int num)
+{
+  g_free (option->choices);
+  g_free (option->choices_display);
+
+  option->num_choices = num;
+  if (num == 0)
+    {
+      option->choices = NULL;
+      option->choices_display = NULL;
+    }
+  else
+    {
+      option->choices = g_new0 (char *, num);
+      option->choices_display = g_new0 (char *, num);
+    }
+}
+
+void
+gtk_printer_option_choices_from_array (GtkPrinterOption   *option,
+                                      int                 num_choices,
+                                      const char        **choices,
+                                      const char        **choices_display)
+{
+  int i;
+  
+  gtk_printer_option_allocate_choices (option, num_choices);
+  for (i = 0; i < num_choices; i++)
+    {
+      option->choices[i] = g_strdup (choices[i]);
+      option->choices_display[i] = g_strdup (choices_display[i]);
+    }
+}
+
+gboolean
+gtk_printer_option_has_choice (GtkPrinterOption     *option,
+                              const char           *choice)
+{
+  int i;
+  
+  for (i = 0; i < option->num_choices; i++)
+    {
+      if (strcmp (option->choices[i], choice) == 0)
+       return TRUE;
+    }
+  
+  return FALSE;
+}
+
+void
+gtk_printer_option_set_activates_default (GtkPrinterOption *option,
+                                         gboolean          activates)
+{
+  g_return_if_fail (GTK_IS_PRINTER_OPTION (option));
+
+  option->activates_default = activates;
+}
+
+gboolean
+gtk_printer_option_get_activates_default (GtkPrinterOption *option)
+{
+  g_return_val_if_fail (GTK_IS_PRINTER_OPTION (option), FALSE);
+
+  return option->activates_default;
+}
diff --git a/gtk/print/gtkprinteroptionprivate.h b/gtk/print/gtkprinteroptionprivate.h
new file mode 100644 (file)
index 0000000..0578e30
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION             (gtk_printer_option_get_type ())
+#define GTK_PRINTER_OPTION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION, GtkPrinterOption))
+#define GTK_IS_PRINTER_OPTION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION))
+
+typedef struct _GtkPrinterOption       GtkPrinterOption;
+typedef struct _GtkPrinterOptionClass  GtkPrinterOptionClass;
+
+#define GTK_PRINTER_OPTION_GROUP_IMAGE_QUALITY "ImageQuality"
+#define GTK_PRINTER_OPTION_GROUP_FINISHING "Finishing"
+
+typedef enum {
+  GTK_PRINTER_OPTION_TYPE_BOOLEAN,
+  GTK_PRINTER_OPTION_TYPE_PICKONE,
+  GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD,
+  GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE,
+  GTK_PRINTER_OPTION_TYPE_PICKONE_REAL,
+  GTK_PRINTER_OPTION_TYPE_PICKONE_INT,
+  GTK_PRINTER_OPTION_TYPE_PICKONE_STRING,
+  GTK_PRINTER_OPTION_TYPE_ALTERNATIVE,
+  GTK_PRINTER_OPTION_TYPE_STRING,
+  GTK_PRINTER_OPTION_TYPE_FILESAVE,
+  GTK_PRINTER_OPTION_TYPE_INFO
+} GtkPrinterOptionType;
+
+struct _GtkPrinterOption
+{
+  GObject parent_instance;
+
+  char *name;
+  char *display_text;
+  GtkPrinterOptionType type;
+
+  char *value;
+
+  int num_choices;
+  char **choices;
+  char **choices_display;
+
+  gboolean activates_default;
+
+  gboolean has_conflict;
+  char *group;
+};
+
+struct _GtkPrinterOptionClass
+{
+  GObjectClass parent_class;
+
+  void (*changed) (GtkPrinterOption *option);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+GDK_AVAILABLE_IN_ALL
+GType   gtk_printer_option_get_type       (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOption *gtk_printer_option_new                    (const char           *name,
+                                                            const char           *display_text,
+                                                            GtkPrinterOptionType  type);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_set                    (GtkPrinterOption     *option,
+                                                            const char           *value);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_set_has_conflict       (GtkPrinterOption     *option,
+                                                            gboolean              has_conflict);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_clear_has_conflict     (GtkPrinterOption     *option);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_set_boolean            (GtkPrinterOption     *option,
+                                                            gboolean              value);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_allocate_choices       (GtkPrinterOption     *option,
+                                                            int                   num);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_choices_from_array     (GtkPrinterOption     *option,
+                                                             int                   num_choices,
+                                                             const char           **choices,
+                                                             const char           **choices_display);
+GDK_AVAILABLE_IN_ALL
+gboolean          gtk_printer_option_has_choice             (GtkPrinterOption     *option,
+                                                           const char           *choice);
+GDK_AVAILABLE_IN_ALL
+void              gtk_printer_option_set_activates_default (GtkPrinterOption     *option,
+                                                           gboolean              activates);
+GDK_AVAILABLE_IN_ALL
+gboolean          gtk_printer_option_get_activates_default (GtkPrinterOption     *option);
+
+
+G_END_DECLS
+
+
+
diff --git a/gtk/print/gtkprinteroptionset.c b/gtk/print/gtkprinteroptionset.c
new file mode 100644 (file)
index 0000000..288fda6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <glib.h>
+#include <gmodule.h>
+
+#include "gtkprinteroptionsetprivate.h"
+#include "gtkprivate.h"
+
+/*****************************************
+ *         GtkPrinterOptionSet    *
+ *****************************************/
+
+enum {
+  CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* ugly side-effect of aliasing */
+#undef gtk_printer_option_set
+
+G_DEFINE_TYPE (GtkPrinterOptionSet, gtk_printer_option_set, G_TYPE_OBJECT)
+
+static void
+gtk_printer_option_set_finalize (GObject *object)
+{
+  GtkPrinterOptionSet *set = GTK_PRINTER_OPTION_SET (object);
+
+  g_hash_table_destroy (set->hash);
+  g_ptr_array_foreach (set->array, (GFunc)g_object_unref, NULL);
+  g_ptr_array_free (set->array, TRUE);
+  
+  G_OBJECT_CLASS (gtk_printer_option_set_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_set_init (GtkPrinterOptionSet *set)
+{
+  set->array = g_ptr_array_new ();
+  set->hash = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+static void
+gtk_printer_option_set_class_init (GtkPrinterOptionSetClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->finalize = gtk_printer_option_set_finalize;
+
+  signals[CHANGED] =
+    g_signal_new (I_("changed"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrinterOptionSetClass, changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+}
+
+
+static void
+emit_changed (GtkPrinterOptionSet *set)
+{
+  g_signal_emit (set, signals[CHANGED], 0);
+}
+
+GtkPrinterOptionSet *
+gtk_printer_option_set_new (void)
+{
+  return g_object_new (GTK_TYPE_PRINTER_OPTION_SET, NULL);
+}
+
+void
+gtk_printer_option_set_remove (GtkPrinterOptionSet *set,
+                              GtkPrinterOption    *option)
+{
+  int i;
+  
+  for (i = 0; i < set->array->len; i++)
+    {
+      if (g_ptr_array_index (set->array, i) == option)
+       {
+         g_ptr_array_remove_index (set->array, i);
+         g_hash_table_remove (set->hash, option->name);
+         g_signal_handlers_disconnect_by_func (option, emit_changed, set);
+
+         g_object_unref (option);
+         break;
+       }
+    }
+}
+
+void
+gtk_printer_option_set_add (GtkPrinterOptionSet *set,
+                           GtkPrinterOption    *option)
+{
+  g_object_ref (option);
+  
+  if (gtk_printer_option_set_lookup (set, option->name))
+    gtk_printer_option_set_remove (set, option);
+    
+  g_ptr_array_add (set->array, option);
+  g_hash_table_insert (set->hash, option->name, option);
+  g_signal_connect_object (option, "changed", G_CALLBACK (emit_changed), set, G_CONNECT_SWAPPED);
+}
+
+GtkPrinterOption *
+gtk_printer_option_set_lookup (GtkPrinterOptionSet *set,
+                              const char          *name)
+{
+  gpointer ptr;
+
+  ptr = g_hash_table_lookup (set->hash, name);
+
+  return GTK_PRINTER_OPTION (ptr);
+}
+
+void
+gtk_printer_option_set_clear_conflicts (GtkPrinterOptionSet *set)
+{
+  gtk_printer_option_set_foreach (set,
+                                 (GtkPrinterOptionSetFunc)gtk_printer_option_clear_has_conflict,
+                                 NULL);
+}
+
+/**
+ * gtk_printer_option_set_get_groups:
+ * @set: a `GtkPrinterOptionSet`
+ *
+ * Gets the groups in this set.
+ *
+ * Returns: (element-type utf8) (transfer full): a list of group names.
+ */
+GList *
+gtk_printer_option_set_get_groups (GtkPrinterOptionSet *set)
+{
+  GtkPrinterOption *option;
+  GList *list = NULL;
+  int i;
+
+  for (i = 0; i < set->array->len; i++)
+    {
+      option = g_ptr_array_index (set->array, i);
+
+      if (g_list_find_custom (list, option->group, (GCompareFunc)g_strcmp0) == NULL)
+       list = g_list_prepend (list, g_strdup (option->group));
+    }
+
+  return g_list_reverse (list);
+}
+
+void
+gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet     *set,
+                                        const char              *group,
+                                        GtkPrinterOptionSetFunc  func,
+                                        gpointer                 user_data)
+{
+  GtkPrinterOption *option;
+  int i;
+
+  for (i = 0; i < set->array->len; i++)
+    {
+      option = g_ptr_array_index (set->array, i);
+
+      if (group == NULL || g_strcmp0 (group, option->group) == 0)
+       func (option, user_data);
+    }
+}
+
+void
+gtk_printer_option_set_foreach (GtkPrinterOptionSet *set,
+                               GtkPrinterOptionSetFunc func,
+                               gpointer user_data)
+{
+  gtk_printer_option_set_foreach_in_group (set, NULL, func, user_data);
+}
diff --git a/gtk/print/gtkprinteroptionsetprivate.h b/gtk/print/gtkprinteroptionsetprivate.h
new file mode 100644 (file)
index 0000000..416a82a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/* This is a "semi-private" header; it is meant only for
+ * alternate GtkPrintDialog backend modules; no stability guarantees
+ * are made at this point
+ */
+#ifndef GTK_PRINT_BACKEND_ENABLE_UNSUPPORTED
+#error "GtkPrintBackend is not supported API for general use"
+#endif
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+#include "gtkprinteroptionprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION_SET             (gtk_printer_option_set_get_type ())
+#define GTK_PRINTER_OPTION_SET(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_SET, GtkPrinterOptionSet))
+#define GTK_IS_PRINTER_OPTION_SET(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_SET))
+
+typedef struct _GtkPrinterOptionSet       GtkPrinterOptionSet;
+typedef struct _GtkPrinterOptionSetClass  GtkPrinterOptionSetClass;
+
+struct _GtkPrinterOptionSet
+{
+  GObject parent_instance;
+
+  /*< private >*/
+  GPtrArray *array;
+  GHashTable *hash;
+};
+
+struct _GtkPrinterOptionSetClass
+{
+  GObjectClass parent_class;
+
+  void (*changed) (GtkPrinterOptionSet *option);
+
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+typedef void (*GtkPrinterOptionSetFunc) (GtkPrinterOption  *option,
+                                        gpointer           user_data);
+
+
+GDK_AVAILABLE_IN_ALL
+GType   gtk_printer_option_set_get_type       (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOptionSet *gtk_printer_option_set_new              (void);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_printer_option_set_add              (GtkPrinterOptionSet     *set,
+                                                             GtkPrinterOption        *option);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_printer_option_set_remove           (GtkPrinterOptionSet     *set,
+                                                             GtkPrinterOption        *option);
+GDK_AVAILABLE_IN_ALL
+GtkPrinterOption *   gtk_printer_option_set_lookup           (GtkPrinterOptionSet     *set,
+                                                             const char              *name);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_printer_option_set_foreach          (GtkPrinterOptionSet     *set,
+                                                             GtkPrinterOptionSetFunc  func,
+                                                             gpointer                 user_data);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_printer_option_set_clear_conflicts  (GtkPrinterOptionSet     *set);
+GDK_AVAILABLE_IN_ALL
+GList *              gtk_printer_option_set_get_groups       (GtkPrinterOptionSet     *set);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_printer_option_set_foreach_in_group (GtkPrinterOptionSet     *set,
+                                                             const char              *group,
+                                                             GtkPrinterOptionSetFunc  func,
+                                                             gpointer                 user_data);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprinteroptionwidget.c b/gtk/print/gtkprinteroptionwidget.c
new file mode 100644 (file)
index 0000000..c14a675
--- /dev/null
@@ -0,0 +1,1192 @@
+/* GtkPrinterOptionWidget
+ * Copyright (C) 2006 Alexander Larsson  <alexl@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <glib/gi18n-lib.h>
+#include "gtkcheckbutton.h"
+#include "gtkdropdown.h"
+#include "gtklistitem.h"
+#include "gtksignallistitemfactory.h"
+#include "gtkentry.h"
+#include "gtkfiledialog.h"
+#include "gtkimage.h"
+#include "gtklabel.h"
+#include "gtkcheckbutton.h"
+#include "gtkgrid.h"
+#include "gtkorientable.h"
+#include "gtkprivate.h"
+#include "gtkstringlist.h"
+
+#include "gtkprinteroptionwidgetprivate.h"
+
+/* This defines the max file length that the file chooser
+ * button should display. The total length will be
+ * FILENAME_LENGTH_MAX+3 because the truncated name is prefixed
+ * with “...”.
+ */
+#define FILENAME_LENGTH_MAX 27
+
+static void gtk_printer_option_widget_finalize (GObject *object);
+
+static void deconstruct_widgets (GtkPrinterOptionWidget *widget);
+static void construct_widgets   (GtkPrinterOptionWidget *widget);
+static void update_widgets      (GtkPrinterOptionWidget *widget);
+
+static char *trim_long_filename (const char *filename);
+
+struct GtkPrinterOptionWidgetPrivate
+{
+  GtkPrinterOption *source;
+  gulong source_changed_handler;
+
+  GtkWidget *check;
+  GtkWidget *combo;
+  GtkWidget *entry;
+  GtkWidget *image;
+  GtkWidget *label;
+  GtkWidget *info_label;
+  GtkWidget *box;
+  GtkWidget *button;
+
+  /* the last location for save to file, that the user selected */
+  GFile *last_location;
+};
+
+enum {
+  CHANGED,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+  PROP_SOURCE
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkPrinterOptionWidget, gtk_printer_option_widget, GTK_TYPE_BOX)
+
+static void gtk_printer_option_widget_set_property (GObject      *object,
+                                                   guint         prop_id,
+                                                   const GValue *value,
+                                                   GParamSpec   *pspec);
+static void gtk_printer_option_widget_get_property (GObject      *object,
+                                                   guint         prop_id,
+                                                   GValue       *value,
+                                                   GParamSpec   *pspec);
+static gboolean gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
+                                                            gboolean   group_cycling);
+
+static void
+gtk_printer_option_widget_class_init (GtkPrinterOptionWidgetClass *class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = (GObjectClass *) class;
+  widget_class = (GtkWidgetClass *) class;
+
+  object_class->finalize = gtk_printer_option_widget_finalize;
+  object_class->set_property = gtk_printer_option_widget_set_property;
+  object_class->get_property = gtk_printer_option_widget_get_property;
+
+  widget_class->mnemonic_activate = gtk_printer_option_widget_mnemonic_activate;
+
+  signals[CHANGED] =
+    g_signal_new (I_("changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrinterOptionWidgetClass, changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+
+  g_object_class_install_property (object_class,
+                                   PROP_SOURCE,
+                                   g_param_spec_object ("source", NULL, NULL,
+                                                       GTK_TYPE_PRINTER_OPTION,
+                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+}
+
+static void
+gtk_printer_option_widget_init (GtkPrinterOptionWidget *widget)
+{
+  widget->priv = gtk_printer_option_widget_get_instance_private (widget);
+
+  gtk_box_set_spacing (GTK_BOX (widget), 12);
+}
+
+static void
+gtk_printer_option_widget_finalize (GObject *object)
+{
+  GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  if (priv->source)
+    {
+      g_signal_handler_disconnect (priv->source,
+                                  priv->source_changed_handler);
+      g_object_unref (priv->source);
+      priv->source = NULL;
+    }
+
+  G_OBJECT_CLASS (gtk_printer_option_widget_parent_class)->finalize (object);
+}
+
+static void
+gtk_printer_option_widget_set_property (GObject         *object,
+                                       guint            prop_id,
+                                       const GValue    *value,
+                                       GParamSpec      *pspec)
+{
+  GtkPrinterOptionWidget *widget;
+
+  widget = GTK_PRINTER_OPTION_WIDGET (object);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      gtk_printer_option_widget_set_source (widget, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_printer_option_widget_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  GtkPrinterOptionWidget *widget = GTK_PRINTER_OPTION_WIDGET (object);
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      g_value_set_object (value, priv->source);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static gboolean
+gtk_printer_option_widget_mnemonic_activate (GtkWidget *widget,
+                                            gboolean   group_cycling)
+{
+  GtkPrinterOptionWidget *powidget = GTK_PRINTER_OPTION_WIDGET (widget);
+  GtkPrinterOptionWidgetPrivate *priv = powidget->priv;
+
+  if (priv->check)
+    return gtk_widget_mnemonic_activate (priv->check, group_cycling);
+  if (priv->combo)
+    return gtk_widget_mnemonic_activate (priv->combo, group_cycling);
+  if (priv->entry)
+    return gtk_widget_mnemonic_activate (priv->entry, group_cycling);
+  if (priv->button)
+    return gtk_widget_mnemonic_activate (priv->button, group_cycling);
+
+  return FALSE;
+}
+
+static void
+emit_changed (GtkPrinterOptionWidget *widget)
+{
+  g_signal_emit (widget, signals[CHANGED], 0);
+}
+
+GtkWidget *
+gtk_printer_option_widget_new (GtkPrinterOption *source)
+{
+  return g_object_new (GTK_TYPE_PRINTER_OPTION_WIDGET, "source", source, NULL);
+}
+
+static void
+source_changed_cb (GtkPrinterOption *source,
+                  GtkPrinterOptionWidget  *widget)
+{
+  update_widgets (widget);
+  emit_changed (widget);
+}
+
+void
+gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget,
+                                     GtkPrinterOption       *source)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  if (source)
+    g_object_ref (source);
+
+  if (priv->source)
+    {
+      g_signal_handler_disconnect (priv->source,
+                                  priv->source_changed_handler);
+      g_object_unref (priv->source);
+    }
+
+  priv->source = source;
+
+  if (source)
+    priv->source_changed_handler =
+      g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), widget);
+
+  construct_widgets (widget);
+  update_widgets (widget);
+
+  g_object_notify (G_OBJECT (widget), "source");
+}
+
+#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ())
+G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject)
+
+struct _GtkStringPair {
+  GObject parent_instance;
+  char *id;
+  char *string;
+};
+
+enum {
+  PROP_ID = 1,
+  PROP_STRING,
+  PROP_NUM_PROPERTIES
+};
+
+G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT);
+
+static void
+gtk_string_pair_init (GtkStringPair *pair)
+{
+}
+
+static void
+gtk_string_pair_finalize (GObject *object)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  g_free (pair->id);
+  g_free (pair->string);
+
+  G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object);
+}
+
+static void
+gtk_string_pair_set_property (GObject      *object,
+                              guint         property_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  switch (property_id)
+    {
+    case PROP_STRING:
+      g_free (pair->string);
+      pair->string = g_value_dup_string (value);
+      break;
+
+    case PROP_ID:
+      g_free (pair->id);
+      pair->id = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_string_pair_get_property (GObject      *object,
+                              guint         property_id,
+                              GValue       *value,
+                              GParamSpec   *pspec)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  switch (property_id)
+    {
+    case PROP_STRING:
+      g_value_set_string (value, pair->string);
+      break;
+
+    case PROP_ID:
+      g_value_set_string (value, pair->id);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_string_pair_class_init (GtkStringPairClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GParamSpec *pspec;
+
+  object_class->finalize = gtk_string_pair_finalize;
+  object_class->set_property = gtk_string_pair_set_property;
+  object_class->get_property = gtk_string_pair_get_property;
+
+  pspec = g_param_spec_string ("string", NULL, NULL,
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_property (object_class, PROP_STRING, pspec);
+
+  pspec = g_param_spec_string ("id", NULL, NULL,
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_property (object_class, PROP_ID, pspec);
+}
+
+static GtkStringPair *
+gtk_string_pair_new (const char *id,
+                     const char *string)
+{
+  return g_object_new (GTK_TYPE_STRING_PAIR,
+                       "id", id,
+                       "string", string,
+                       NULL);
+}
+
+static const char *
+gtk_string_pair_get_string (GtkStringPair *pair)
+{
+  return pair->string;
+}
+
+static const char *
+gtk_string_pair_get_id (GtkStringPair *pair)
+{
+  return pair->id;
+}
+
+static void
+combo_box_set_model (GtkWidget *combo_box)
+{
+  GListStore *store;
+
+  store = g_list_store_new (GTK_TYPE_STRING_PAIR);
+  gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store));
+  g_object_unref (store);
+}
+
+static void
+setup_no_item (GtkSignalListItemFactory *factory,
+               GtkListItem              *item)
+{
+}
+
+static void
+setup_list_item (GtkSignalListItemFactory *factory,
+                 GtkListItem              *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new ("");
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_list_item (GtkSignalListItemFactory *factory,
+                GtkListItem              *item)
+{
+  GtkStringPair *pair;
+  GtkWidget *label;
+
+  pair = gtk_list_item_get_item (item);
+  label = gtk_list_item_get_child (item);
+
+  gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair));
+}
+
+static void
+combo_box_set_view (GtkWidget *combo_box)
+{
+  GtkListItemFactory *factory;
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory);
+  g_object_unref (factory);
+}
+
+static void
+selected_changed (GtkDropDown *dropdown,
+                  GParamSpec *pspec,
+                  gpointer data)
+{
+  GListModel *model;
+  guint selected;
+  GtkStringPair *pair;
+  GtkWidget *entry = data;
+
+  model = gtk_drop_down_get_model (dropdown);
+  selected = gtk_drop_down_get_selected (dropdown);
+
+  pair = g_list_model_get_item (model, selected);
+  if (pair)
+    {
+      gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair));
+      g_object_unref (pair);
+    }
+  else
+    gtk_editable_set_text (GTK_EDITABLE (entry), "");
+
+}
+
+static GtkWidget *
+combo_box_entry_new (void)
+{
+  GtkWidget *hbox, *entry, *button;
+  GtkListItemFactory *factory;
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_add_css_class (hbox, "linked");
+
+  entry = gtk_entry_new ();
+  button = gtk_drop_down_new (NULL, NULL);
+  combo_box_set_model (button);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory);
+  g_object_unref (factory);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory);
+  g_object_unref (factory);
+
+  g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry);
+
+  gtk_box_append (GTK_BOX (hbox), entry);
+  gtk_box_append (GTK_BOX (hbox), button);
+
+  return hbox;
+}
+
+static GtkWidget *
+combo_box_new (void)
+{
+  GtkWidget *combo_box;
+
+  combo_box = gtk_drop_down_new (NULL, NULL);
+
+  combo_box_set_model (combo_box);
+  combo_box_set_view (combo_box);
+
+  return combo_box;
+}
+
+static void
+combo_box_append (GtkWidget   *combo,
+                  const char *display_text,
+                  const char *value)
+{
+  GtkWidget *dropdown;
+  GListModel *model;
+  GtkStringPair *object;
+
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
+
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+
+  object = gtk_string_pair_new (value, display_text);
+  g_list_store_append (G_LIST_STORE (model), object);
+  g_object_unref (object);
+}
+
+static void
+combo_box_set (GtkWidget   *combo,
+               const char *value)
+{
+  GtkWidget *dropdown;
+  GListModel *model;
+  guint i;
+
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
+
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+
+  for (i = 0; i < g_list_model_get_n_items (model); i++)
+    {
+      GtkStringPair *item = g_list_model_get_item (model, i);
+      if (strcmp (value, gtk_string_pair_get_id (item)) == 0)
+        {
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
+          g_object_unref (item);
+          break;
+        }
+      g_object_unref (item);
+    }
+}
+
+static char *
+combo_box_get (GtkWidget *combo, gboolean *custom)
+{
+  GtkWidget *dropdown;
+  GListModel *model;
+  guint selected;
+  gpointer item;
+  const char *id;
+  const char *string;
+
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
+
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
+  item = g_list_model_get_item (model, selected);
+  if (item)
+    {
+      id = gtk_string_pair_get_id (item);
+      string = gtk_string_pair_get_string (item);
+      g_object_unref (item);
+    }
+  else
+    {
+      id = "";
+      string = NULL;
+    }
+
+  if (dropdown == combo) // no entry
+    {
+      *custom = FALSE;
+      return g_strdup (id);
+    }
+  else
+    {
+      const char *text;
+
+      text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo)));
+      if (g_strcmp0 (text, string) == 0)
+        {
+          *custom = FALSE;
+          return g_strdup (id);
+        }
+      else
+        {
+          *custom = TRUE;
+          return g_strdup (text);
+        }
+    }
+}
+
+static void
+deconstruct_widgets (GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  g_clear_pointer (&priv->check, gtk_widget_unparent);
+  g_clear_pointer (&priv->combo, gtk_widget_unparent);
+  g_clear_pointer (&priv->entry, gtk_widget_unparent);
+  g_clear_pointer (&priv->image, gtk_widget_unparent);
+  g_clear_pointer (&priv->label, gtk_widget_unparent);
+  g_clear_pointer (&priv->info_label, gtk_widget_unparent);
+}
+
+static void
+check_toggled_cb (GtkCheckButton         *check_button,
+                 GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  g_signal_handler_block (priv->source, priv->source_changed_handler);
+  gtk_printer_option_set_boolean (priv->source,
+                                  gtk_check_button_get_active (check_button));
+  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+  emit_changed (widget);
+}
+
+static void
+dialog_response_callback (GObject *source,
+                          GAsyncResult *result,
+                          gpointer data)
+{
+  GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
+  GtkPrinterOptionWidget *widget = data;
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  GFile *new_location = NULL;
+  char *uri = NULL;
+
+  new_location = gtk_file_dialog_save_finish (dialog, result, NULL);
+  if (new_location)
+    {
+      GFileInfo *info;
+
+      info = g_file_query_info (new_location,
+                                "standard::display-name",
+                                0,
+                                NULL,
+                                NULL);
+      if (info != NULL)
+        {
+          const char *filename_utf8 = g_file_info_get_display_name (info);
+
+          char *filename_short = trim_long_filename (filename_utf8);
+          gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
+
+          g_free (filename_short);
+          g_object_unref (info);
+        }
+      else
+        {
+          const char *path = g_file_peek_path (new_location);
+          char *filename_utf8 = g_utf8_make_valid (path, -1);
+
+          char *filename_short = trim_long_filename (filename_utf8);
+          gtk_button_set_label (GTK_BUTTON (priv->button), filename_short);
+
+          g_free (filename_short);
+          g_free (filename_utf8);
+        }
+    }
+
+  if (new_location)
+    uri = g_file_get_uri (new_location);
+  else
+    uri = g_file_get_uri (priv->last_location);
+
+  if (uri != NULL)
+    {
+      gtk_printer_option_set (priv->source, uri);
+      emit_changed (widget);
+      g_free (uri);
+    }
+
+  g_clear_object (&new_location);
+  g_clear_object (&priv->last_location);
+
+  /* unblock the handler which was blocked in the filesave_choose_cb function */
+  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+}
+
+static void
+filesave_choose_cb (GtkWidget              *button,
+                    GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  GtkFileDialog *dialog;
+
+  /* this will be unblocked in the dialog_response_callback function */
+  g_signal_handler_block (priv->source, priv->source_changed_handler);
+
+  dialog = gtk_file_dialog_new ();
+  gtk_file_dialog_set_title (dialog, _("Select a filename"));
+
+  /* select the current filename in the dialog */
+  if (priv->source != NULL && priv->source->value != NULL)
+    {
+      priv->last_location = g_file_new_for_uri (priv->source->value);
+      if (priv->last_location)
+        {
+          if (g_file_query_file_type (priv->last_location, 0, NULL) == G_FILE_TYPE_DIRECTORY)
+            gtk_file_dialog_set_initial_folder (dialog, priv->last_location);
+          else
+            gtk_file_dialog_set_initial_file (dialog, priv->last_location);
+        }
+    }
+
+  gtk_file_dialog_save (dialog,
+                        GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (widget))),
+                        NULL,
+                        dialog_response_callback, widget);
+}
+
+static char *
+filter_numeric (const char *val,
+                gboolean     allow_neg,
+               gboolean     allow_dec,
+                gboolean    *changed_out)
+{
+  char *filtered_val;
+  int i, j;
+  int len = strlen (val);
+  gboolean dec_set = FALSE;
+
+  filtered_val = g_malloc (len + 1);
+
+  for (i = 0, j = 0; i < len; i++)
+    {
+      if (isdigit (val[i]))
+        {
+          filtered_val[j] = val[i];
+         j++;
+       }
+      else if (allow_dec && !dec_set &&
+               (val[i] == '.' || val[i] == ','))
+        {
+         /* allow one period or comma
+          * we should be checking locals
+          * but this is good enough for now
+          */
+          filtered_val[j] = val[i];
+         dec_set = TRUE;
+         j++;
+       }
+      else if (allow_neg && i == 0 && val[0] == '-')
+        {
+          filtered_val[0] = val[0];
+         j++;
+       }
+    }
+
+  filtered_val[j] = '\0';
+  *changed_out = !(i == j);
+
+  return filtered_val;
+}
+
+static void
+combo_changed_cb (GtkWidget              *combo,
+                  GParamSpec             *pspec,
+                 GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  char *value;
+  char *filtered_val = NULL;
+  gboolean changed;
+  gboolean custom = TRUE;
+
+  g_signal_handler_block (priv->source, priv->source_changed_handler);
+
+  value = combo_box_get (priv->combo, &custom);
+
+  /* Handle constraints if the user entered a custom value. */
+  if (custom)
+    {
+      switch (priv->source->type)
+        {
+        case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+          filtered_val = filter_numeric (value, FALSE, FALSE, &changed);
+          break;
+        case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+          filtered_val = filter_numeric (value, TRUE, FALSE, &changed);
+          break;
+        case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+          filtered_val = filter_numeric (value, TRUE, TRUE, &changed);
+          break;
+        case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+        case GTK_PRINTER_OPTION_TYPE_PICKONE:
+        case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+        case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+        case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+        case GTK_PRINTER_OPTION_TYPE_STRING:
+        case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+        case GTK_PRINTER_OPTION_TYPE_INFO:
+        default:
+          break;
+        }
+    }
+
+  if (filtered_val)
+    {
+      g_free (value);
+
+      if (changed)
+        {
+          GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+          gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val);
+        }
+      value = filtered_val;
+    }
+
+  if (value)
+    gtk_printer_option_set (priv->source, value);
+  g_free (value);
+  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+  emit_changed (widget);
+}
+
+static void
+entry_changed_cb (GtkWidget              *entry,
+                 GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  const char *value;
+
+  g_signal_handler_block (priv->source, priv->source_changed_handler);
+  value = gtk_editable_get_text (GTK_EDITABLE (entry));
+  if (value)
+    gtk_printer_option_set (priv->source, value);
+  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+  emit_changed (widget);
+}
+
+
+static void
+radio_changed_cb (GtkWidget              *button,
+                 GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  char *value;
+
+  g_signal_handler_block (priv->source, priv->source_changed_handler);
+  value = g_object_get_data (G_OBJECT (button), "value");
+  if (value)
+    gtk_printer_option_set (priv->source, value);
+  g_signal_handler_unblock (priv->source, priv->source_changed_handler);
+  emit_changed (widget);
+}
+
+static void
+alternative_set (GtkWidget   *box,
+                 const char *value)
+{
+  GtkWidget *child;
+
+  for (child = gtk_widget_get_first_child (box);
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      char *v = g_object_get_data (G_OBJECT (child), "value");
+
+      if (strcmp (value, v) == 0)
+        {
+          gtk_check_button_set_active (GTK_CHECK_BUTTON (child), TRUE);
+          break;
+        }
+    }
+}
+
+static void
+alternative_append (GtkWidget              *box,
+                   const char             *label,
+                    const char             *value,
+                   GtkPrinterOptionWidget *widget,
+                   GtkWidget              **group)
+{
+  GtkWidget *button;
+
+  button = gtk_check_button_new_with_label (label);
+  if (*group)
+    gtk_check_button_set_group (GTK_CHECK_BUTTON (button), GTK_CHECK_BUTTON (*group));
+  else
+    *group = button;
+
+  gtk_widget_set_valign (button, GTK_ALIGN_BASELINE_FILL);
+  gtk_box_append (GTK_BOX (box), button);
+
+  g_object_set_data (G_OBJECT (button), "value", (gpointer)value);
+  g_signal_connect (button, "toggled", G_CALLBACK (radio_changed_cb), widget);
+}
+
+static void
+construct_widgets (GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  GtkPrinterOption *source;
+  char *text;
+  int i;
+  GtkWidget *group;
+
+  source = priv->source;
+
+  deconstruct_widgets (widget);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
+
+  if (source == NULL)
+    {
+      const char * strings[2];
+      strings[0] = _("Not available");
+      strings[1] = NULL;
+      priv->combo = gtk_drop_down_new_from_strings (strings);
+      gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
+      gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
+      gtk_box_append (GTK_BOX (widget), priv->combo);
+    }
+  else switch (source->type)
+    {
+    case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+      priv->check = gtk_check_button_new_with_mnemonic (source->display_text);
+      g_signal_connect (priv->check, "toggled", G_CALLBACK (check_toggled_cb), widget);
+      gtk_box_append (GTK_BOX (widget), priv->check);
+      break;
+    case GTK_PRINTER_OPTION_TYPE_PICKONE:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+      if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE)
+        {
+          priv->combo = combo_box_new ();
+        }
+      else
+        {
+          priv->combo = combo_box_entry_new ();
+
+          if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ||
+              source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
+            {
+              GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+              gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
+            }
+        }
+
+      for (i = 0; i < source->num_choices; i++)
+        combo_box_append (priv->combo,
+                          source->choices_display[i],
+                          source->choices[i]);
+      gtk_box_append (GTK_BOX (widget), priv->combo);
+      if (GTK_IS_DROP_DOWN (priv->combo))
+        g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget);
+      else
+        g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK (combo_changed_cb), widget);
+
+      text = g_strdup_printf ("%s:", source->display_text);
+      priv->label = gtk_label_new_with_mnemonic (text);
+      g_free (text);
+      break;
+
+    case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+      group = NULL;
+      priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+      gtk_widget_set_valign (priv->box, GTK_ALIGN_BASELINE_FILL);
+      gtk_box_append (GTK_BOX (widget), priv->box);
+      for (i = 0; i < source->num_choices; i++)
+        {
+          alternative_append (priv->box,
+                              source->choices_display[i],
+                              source->choices[i],
+                              widget,
+                              &group);
+          /* for mnemonic activation */
+          if (i == 0)
+            priv->button = group;
+        }
+
+      if (source->display_text)
+       {
+         text = g_strdup_printf ("%s:", source->display_text);
+         priv->label = gtk_label_new_with_mnemonic (text);
+          gtk_widget_set_valign (priv->label, GTK_ALIGN_BASELINE_FILL);
+         g_free (text);
+       }
+      break;
+
+    case GTK_PRINTER_OPTION_TYPE_STRING:
+      priv->entry = gtk_entry_new ();
+      gtk_entry_set_activates_default (GTK_ENTRY (priv->entry),
+                                       gtk_printer_option_get_activates_default (source));
+      gtk_box_append (GTK_BOX (widget), priv->entry);
+      g_signal_connect (priv->entry, "changed", G_CALLBACK (entry_changed_cb), widget);
+
+      text = g_strdup_printf ("%s:", source->display_text);
+      priv->label = gtk_label_new_with_mnemonic (text);
+      g_free (text);
+
+      break;
+
+    case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+      priv->button = gtk_button_new ();
+      gtk_box_append (GTK_BOX (widget), priv->button);
+      g_signal_connect (priv->button, "clicked", G_CALLBACK (filesave_choose_cb), widget);
+
+      text = g_strdup_printf ("%s:", source->display_text);
+      priv->label = gtk_label_new_with_mnemonic (text);
+      g_free (text);
+
+      break;
+
+    case GTK_PRINTER_OPTION_TYPE_INFO:
+      priv->info_label = gtk_label_new (NULL);
+      gtk_label_set_selectable (GTK_LABEL (priv->info_label), TRUE);
+      gtk_box_append (GTK_BOX (widget), priv->info_label);
+
+      text = g_strdup_printf ("%s:", source->display_text);
+      priv->label = gtk_label_new_with_mnemonic (text);
+      g_free (text);
+
+      break;
+
+    default:
+      break;
+    }
+
+  priv->image = gtk_image_new_from_icon_name ("dialog-warning");
+  gtk_box_append (GTK_BOX (widget), priv->image);
+}
+
+/*
+ * If the filename exceeds FILENAME_LENGTH_MAX, then trim it and replace
+ * the first three letters with three dots.
+ */
+static char *
+trim_long_filename (const char *filename)
+{
+  const char *home;
+  int len, offset;
+  char *result;
+
+  home = g_get_home_dir ();
+  if (g_str_has_prefix (filename, home))
+    {
+      char *homeless_filename;
+
+      offset = g_utf8_strlen (home, -1);
+      len = g_utf8_strlen (filename, -1);
+      homeless_filename = g_utf8_substring (filename, offset, len);
+      result = g_strconcat ("~", homeless_filename, NULL);
+      g_free (homeless_filename);
+    }
+  else
+    result = g_strdup (filename);
+
+  len = g_utf8_strlen (result, -1);
+  if (len > FILENAME_LENGTH_MAX)
+    {
+      char *suffix;
+
+      suffix = g_utf8_substring (result, len - FILENAME_LENGTH_MAX, len);
+      g_free (result);
+      result = g_strconcat ("...", suffix, NULL);
+      g_free (suffix);
+    }
+
+  return result;
+}
+
+static void
+update_widgets (GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+  GtkPrinterOption *source;
+
+  source = priv->source;
+
+  if (source == NULL)
+    {
+      gtk_widget_set_visible (priv->image, FALSE);
+      return;
+    }
+
+  switch (source->type)
+    {
+    case GTK_PRINTER_OPTION_TYPE_BOOLEAN:
+      if (g_ascii_strcasecmp (source->value, "True") == 0)
+       gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), TRUE);
+      else
+       gtk_check_button_set_active (GTK_CHECK_BUTTON (priv->check), FALSE);
+      break;
+    case GTK_PRINTER_OPTION_TYPE_PICKONE:
+      combo_box_set (priv->combo, source->value);
+      break;
+    case GTK_PRINTER_OPTION_TYPE_ALTERNATIVE:
+      alternative_set (priv->box, source->value);
+      break;
+    case GTK_PRINTER_OPTION_TYPE_STRING:
+      gtk_editable_set_text (GTK_EDITABLE (priv->entry), source->value);
+      break;
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_REAL:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
+    case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
+      {
+        GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+        if (gtk_printer_option_has_choice (source, source->value))
+          combo_box_set (priv->combo, source->value);
+        else
+          gtk_editable_set_text (GTK_EDITABLE (entry), source->value);
+
+        break;
+      }
+    case GTK_PRINTER_OPTION_TYPE_FILESAVE:
+      {
+        char *text;
+        char *filename;
+
+        filename = g_filename_from_uri (source->value, NULL, NULL);
+        if (filename != NULL)
+          {
+            text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+            if (text != NULL)
+              {
+                char *short_filename;
+
+                short_filename = trim_long_filename (text);
+                gtk_button_set_label (GTK_BUTTON (priv->button), short_filename);
+                g_free (short_filename);
+              }
+
+            g_free (text);
+            g_free (filename);
+          }
+        else
+          gtk_button_set_label (GTK_BUTTON (priv->button), source->value);
+        break;
+      }
+    case GTK_PRINTER_OPTION_TYPE_INFO:
+      gtk_label_set_text (GTK_LABEL (priv->info_label), source->value);
+      break;
+    default:
+      break;
+    }
+
+  gtk_widget_set_visible (priv->image, source->has_conflict);
+}
+
+gboolean
+gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *widget)
+{
+  return widget->priv->label != NULL;
+}
+
+GtkWidget *
+gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget  *widget)
+{
+  return widget->priv->label;
+}
+
+const char *
+gtk_printer_option_widget_get_value (GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOptionWidgetPrivate *priv = widget->priv;
+
+  if (priv->source)
+    return priv->source->value;
+
+  return "";
+}
diff --git a/gtk/print/gtkprinteroptionwidgetprivate.h b/gtk/print/gtkprinteroptionwidgetprivate.h
new file mode 100644 (file)
index 0000000..dac14bc
--- /dev/null
@@ -0,0 +1,72 @@
+/* GtkPrinterOptionWidget 
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <gtk/gtk.h>
+#include "gtkprinteroptionprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINTER_OPTION_WIDGET                  (gtk_printer_option_widget_get_type ())
+#define GTK_PRINTER_OPTION_WIDGET(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidget))
+#define GTK_PRINTER_OPTION_WIDGET_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
+#define GTK_IS_PRINTER_OPTION_WIDGET(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET))
+#define GTK_IS_PRINTER_OPTION_WIDGET_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER_OPTION_WIDGET))
+#define GTK_PRINTER_OPTION_WIDGET_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER_OPTION_WIDGET, GtkPrinterOptionWidgetClass))
+
+
+typedef struct _GtkPrinterOptionWidget         GtkPrinterOptionWidget;
+typedef struct _GtkPrinterOptionWidgetClass    GtkPrinterOptionWidgetClass;
+typedef struct GtkPrinterOptionWidgetPrivate   GtkPrinterOptionWidgetPrivate;
+
+struct _GtkPrinterOptionWidget
+{
+  GtkBox parent_instance;
+
+  GtkPrinterOptionWidgetPrivate *priv;
+};
+
+struct _GtkPrinterOptionWidgetClass
+{
+  GtkBoxClass parent_class;
+
+  void (*changed) (GtkPrinterOptionWidget *widget);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+GDK_AVAILABLE_IN_ALL
+GType       gtk_printer_option_widget_get_type           (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkWidget   *gtk_printer_option_widget_new                (GtkPrinterOption       *source);
+GDK_AVAILABLE_IN_ALL
+void         gtk_printer_option_widget_set_source         (GtkPrinterOptionWidget *setting,
+                                                          GtkPrinterOption       *source);
+GDK_AVAILABLE_IN_ALL
+gboolean     gtk_printer_option_widget_has_external_label (GtkPrinterOptionWidget *setting);
+GDK_AVAILABLE_IN_ALL
+GtkWidget   *gtk_printer_option_widget_get_external_label (GtkPrinterOptionWidget *setting);
+GDK_AVAILABLE_IN_ALL
+const char *gtk_printer_option_widget_get_value          (GtkPrinterOptionWidget *setting);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprinterprivate.h b/gtk/print/gtkprinterprivate.h
new file mode 100644 (file)
index 0000000..451588e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "gtkunixprint.h"
+#include "gtkprinteroptionsetprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_PRINTER_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINTER, GtkPrinterClass))
+#define GTK_IS_PRINTER_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINTER))
+#define GTK_PRINTER_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINTER, GtkPrinterClass))
+
+typedef struct _GtkPrinterClass     GtkPrinterClass;
+typedef struct _GtkPrinterPrivate   GtkPrinterPrivate;
+
+struct _GtkPrinter
+{
+  GObject parent_instance;
+};
+
+struct _GtkPrinterClass
+{
+  GObjectClass parent_class;
+
+  void (*details_acquired) (GtkPrinter *printer,
+                            gboolean    success);
+};
+
+GtkPrinterOptionSet *_gtk_printer_get_options               (GtkPrinter          *printer,
+                                                            GtkPrintSettings    *settings,
+                                                            GtkPageSetup        *page_setup,
+                                                            GtkPrintCapabilities capabilities);
+gboolean             _gtk_printer_mark_conflicts            (GtkPrinter          *printer,
+                                                            GtkPrinterOptionSet *options);
+void                 _gtk_printer_get_settings_from_options (GtkPrinter          *printer,
+                                                            GtkPrinterOptionSet *options,
+                                                            GtkPrintSettings    *settings);
+void                 _gtk_printer_prepare_for_print         (GtkPrinter          *printer,
+                                                            GtkPrintJob         *print_job,
+                                                            GtkPrintSettings    *settings,
+                                                            GtkPageSetup        *page_setup);
+cairo_surface_t *    _gtk_printer_create_cairo_surface      (GtkPrinter          *printer,
+                                                            GtkPrintSettings    *settings,
+                                                            double               width,
+                                                            double               height,
+                                                            GIOChannel          *cache_io);
+GHashTable *         _gtk_printer_get_custom_widgets        (GtkPrinter          *printer);
+
+/* GtkPrintJob private methods: */
+GDK_AVAILABLE_IN_ALL
+void gtk_print_job_set_status (GtkPrintJob   *job,
+                              GtkPrintStatus status);
+
+G_END_DECLS
diff --git a/gtk/print/gtkprintjob.c b/gtk/print/gtkprintjob.c
new file mode 100644 (file)
index 0000000..b295d8d
--- /dev/null
@@ -0,0 +1,1001 @@
+/* GtkPrintJob
+ * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * GtkPrintJob:
+ *
+ * A `GtkPrintJob` object represents a job that is sent to a printer.
+ *
+ * You only need to deal directly with print jobs if you use the
+ * non-portable [class@Gtk.PrintUnixDialog] API.
+ *
+ * Use [method@Gtk.PrintJob.get_surface] to obtain the cairo surface
+ * onto which the pages must be drawn. Use [method@Gtk.PrintJob.send]
+ * to send the finished job to the printer. If you don’t use cairo
+ * `GtkPrintJob` also supports printing of manually generated PostScript,
+ * via [method@Gtk.PrintJob.set_source_file].
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glib/gstdio.h>
+#include "gtkprivate.h"
+
+#include "gtkprintjob.h"
+#include "gtkprinter.h"
+#include "gtkprinterprivate.h"
+#include "gtkprintbackendprivate.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+typedef struct _GtkPrintJobClass     GtkPrintJobClass;
+
+struct _GtkPrintJob
+{
+  GObject parent_instance;
+
+  char *title;
+
+  GIOChannel *spool_io;
+  cairo_surface_t *surface;
+
+  GtkPrintStatus status;
+  GtkPrintBackend *backend;
+  GtkPrinter *printer;
+  GtkPrintSettings *settings;
+  GtkPageSetup *page_setup;
+
+  GtkPrintPages print_pages;
+  GtkPageRange *page_ranges;
+  int num_page_ranges;
+  GtkPageSet page_set;
+  int num_copies;
+  double scale;
+  guint number_up;
+  GtkNumberUpLayout number_up_layout;
+
+  guint printer_set           : 1;
+  guint page_setup_set        : 1;
+  guint settings_set          : 1;
+  guint track_print_status    : 1;
+  guint rotate_to_orientation : 1;
+  guint collate               : 1;
+  guint reverse               : 1;
+};
+
+struct _GtkPrintJobClass
+{
+  GObjectClass parent_class;
+
+  void (*status_changed) (GtkPrintJob *job);
+};
+
+static void     gtk_print_job_finalize     (GObject               *object);
+static void     gtk_print_job_set_property (GObject               *object,
+                                           guint                  prop_id,
+                                           const GValue          *value,
+                                           GParamSpec            *pspec);
+static void     gtk_print_job_get_property (GObject               *object,
+                                           guint                  prop_id,
+                                           GValue                *value,
+                                           GParamSpec            *pspec);
+static void     gtk_print_job_constructed  (GObject               *object);
+
+enum {
+  STATUS_CHANGED,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+  PROP_TITLE,
+  PROP_PRINTER,
+  PROP_PAGE_SETUP,
+  PROP_SETTINGS,
+  PROP_TRACK_PRINT_STATUS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
+
+static void
+gtk_print_job_class_init (GtkPrintJobClass *class)
+{
+  GObjectClass *object_class;
+  object_class = (GObjectClass *) class;
+
+  object_class->finalize = gtk_print_job_finalize;
+  object_class->constructed = gtk_print_job_constructed;
+  object_class->set_property = gtk_print_job_set_property;
+  object_class->get_property = gtk_print_job_get_property;
+
+  /**
+   * GtkPrintJob:title: (attributes org.gtk.Property.get=gtk_print_job_get_title)
+   *
+   * The title of the print job.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_TITLE,
+                                   g_param_spec_string ("title", NULL, NULL,
+                                                       NULL,
+                                                       GTK_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrintJob:printer: (attributes org.gtk.Property.get=gtk_print_job_get_printer)
+   *
+   * The printer to send the job to.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PRINTER,
+                                   g_param_spec_object ("printer", NULL, NULL,
+                                                       GTK_TYPE_PRINTER,
+                                                       GTK_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrintJob:settings: (attributes org.gtk.Property.get=gtk_print_job_get_settings)
+   *
+   * Printer settings.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_SETTINGS,
+                                   g_param_spec_object ("settings", NULL, NULL,
+                                                       GTK_TYPE_PRINT_SETTINGS,
+                                                       GTK_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrintJob:page-setup:
+   *
+   * Page setup.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PAGE_SETUP,
+                                   g_param_spec_object ("page-setup", NULL, NULL,
+                                                       GTK_TYPE_PAGE_SETUP,
+                                                       GTK_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GtkPrintJob:track-print-status: (attributes org.gtk.Property.get=gtk_print_job_get_track_print_status org.gtk.Property.set=gtk_print_job_set_track_print_status)
+   *
+   * %TRUE if the print job will continue to emit status-changed
+   * signals after the print data has been setn to the printer.
+   */
+  g_object_class_install_property (object_class,
+                                  PROP_TRACK_PRINT_STATUS,
+                                  g_param_spec_boolean ("track-print-status", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintJob::status-changed:
+   * @job: the `GtkPrintJob` object on which the signal was emitted
+   *
+   * Emitted when the status of a job changes.
+   *
+   * The signal handler can use [method@Gtk.PrintJob.get_status]
+   * to obtain the new status.
+   */
+  signals[STATUS_CHANGED] =
+    g_signal_new (I_("status-changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+}
+
+static void
+gtk_print_job_init (GtkPrintJob *job)
+{
+  job->spool_io = NULL;
+
+  job->title = g_strdup ("");
+  job->surface = NULL;
+  job->backend = NULL;
+  job->printer = NULL;
+
+  job->printer_set = FALSE;
+  job->settings_set = FALSE;
+  job->page_setup_set = FALSE;
+  job->status = GTK_PRINT_STATUS_INITIAL;
+  job->track_print_status = FALSE;
+
+  job->print_pages = GTK_PRINT_PAGES_ALL;
+  job->page_ranges = NULL;
+  job->num_page_ranges = 0;
+  job->collate = FALSE;
+  job->reverse = FALSE;
+  job->num_copies = 1;
+  job->scale = 1.0;
+  job->page_set = GTK_PAGE_SET_ALL;
+  job->rotate_to_orientation = FALSE;
+  job->number_up = 1;
+  job->number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+}
+
+
+static void
+gtk_print_job_constructed (GObject *object)
+{
+  GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+  G_OBJECT_CLASS (gtk_print_job_parent_class)->constructed (object);
+
+  g_assert (job->printer_set &&
+           job->settings_set &&
+           job->page_setup_set);
+  
+  _gtk_printer_prepare_for_print (job->printer,
+                                 job,
+                                 job->settings,
+                                 job->page_setup);
+}
+
+
+static void
+gtk_print_job_finalize (GObject *object)
+{
+  GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+  if (job->surface)
+    cairo_surface_destroy (job->surface);
+
+  if (job->backend)
+    g_object_unref (job->backend);
+
+  if (job->spool_io != NULL)
+    {
+      g_io_channel_unref (job->spool_io);
+      job->spool_io = NULL;
+    }
+
+  if (job->printer)
+    g_object_unref (job->printer);
+
+  if (job->settings)
+    g_object_unref (job->settings);
+
+  if (job->page_setup)
+    g_object_unref (job->page_setup);
+
+  g_free (job->page_ranges);
+  job->page_ranges = NULL;
+
+  g_free (job->title);
+  job->title = NULL;
+
+  G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_print_job_new:
+ * @title: the job title
+ * @printer: a `GtkPrinter`
+ * @settings: a `GtkPrintSettings`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Creates a new `GtkPrintJob`.
+ *
+ * Returns: a new `GtkPrintJob`
+ */
+GtkPrintJob *
+gtk_print_job_new (const char       *title,
+                  GtkPrinter       *printer,
+                  GtkPrintSettings *settings,
+                  GtkPageSetup     *page_setup)
+{
+  GObject *result;
+  result = g_object_new (GTK_TYPE_PRINT_JOB,
+                         "title", title,
+                        "printer", printer,
+                        "settings", settings,
+                        "page-setup", page_setup,
+                        NULL);
+  return (GtkPrintJob *) result;
+}
+
+/**
+ * gtk_print_job_get_settings: (attributes org.gtk.Method.get_property=settings)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrintSettings` of the print job.
+ *
+ * Returns: (transfer none): the settings of @job
+ */
+GtkPrintSettings *
+gtk_print_job_get_settings (GtkPrintJob *job)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+  
+  return job->settings;
+}
+
+/**
+ * gtk_print_job_get_printer: (attributes org.gtk.Method.get_property=printer)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrinter` of the print job.
+ *
+ * Returns: (transfer none): the printer of @job
+ */
+GtkPrinter *
+gtk_print_job_get_printer (GtkPrintJob *job)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+  
+  return job->printer;
+}
+
+/**
+ * gtk_print_job_get_title: (attributes org.gtk.Method.get_property=title)
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the job title.
+ *
+ * Returns: the title of @job
+ */
+const char *
+gtk_print_job_get_title (GtkPrintJob *job)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+  
+  return job->title;
+}
+
+/**
+ * gtk_print_job_get_status:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the status of the print job.
+ *
+ * Returns: the status of @job
+ */
+GtkPrintStatus
+gtk_print_job_get_status (GtkPrintJob *job)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
+  
+  return job->status;
+}
+
+void
+gtk_print_job_set_status (GtkPrintJob   *job,
+                         GtkPrintStatus status)
+{
+  g_return_if_fail (GTK_IS_PRINT_JOB (job));
+
+  if (job->status == status)
+    return;
+
+  job->status = status;
+  g_signal_emit (job, signals[STATUS_CHANGED], 0);
+}
+
+/**
+ * gtk_print_job_set_source_file:
+ * @job: a `GtkPrintJob`
+ * @filename: (type filename): the file to be printed
+ * @error: return location for errors
+ *
+ * Make the `GtkPrintJob` send an existing document to the
+ * printing system.
+ *
+ * The file can be in any format understood by the platforms
+ * printing system (typically PostScript, but on many platforms
+ * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
+ * [method@Gtk.Printer.accepts_ps].
+ *
+ * Returns: %FALSE if an error occurred
+ */
+gboolean
+gtk_print_job_set_source_file (GtkPrintJob *job,
+                              const char *filename,
+                              GError     **error)
+{
+  GError *tmp_error;
+
+  tmp_error = NULL;
+
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+
+  if (job->spool_io != NULL)
+    g_io_channel_unref (job->spool_io);
+
+  job->spool_io = g_io_channel_new_file (filename, "r", &tmp_error);
+
+  if (tmp_error == NULL)
+    g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
+
+  if (tmp_error != NULL)
+    {
+      g_propagate_error (error, tmp_error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * gtk_print_job_set_source_fd:
+ * @job: a `GtkPrintJob`
+ * @fd: a file descriptor
+ * @error: return location for errors
+ *
+ * Make the `GtkPrintJob` send an existing document to the
+ * printing system.
+ *
+ * The file can be in any format understood by the platforms
+ * printing system (typically PostScript, but on many platforms
+ * PDF may work too). See [method@Gtk.Printer.accepts_pdf] and
+ * [method@Gtk.Printer.accepts_ps].
+ *
+ * This is similar to [method@Gtk.PrintJob.set_source_file],
+ * but takes expects an open file descriptor for the file,
+ * instead of a filename.
+ *
+ * Returns: %FALSE if an error occurred
+ */
+gboolean
+gtk_print_job_set_source_fd (GtkPrintJob  *job,
+                             int           fd,
+                             GError      **error)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+  g_return_val_if_fail (fd >= 0, FALSE);
+
+  if (job->spool_io != NULL)
+    g_io_channel_unref (job->spool_io);
+
+  job->spool_io = g_io_channel_unix_new (fd);
+  if (g_io_channel_set_encoding (job->spool_io, NULL, error) != G_IO_STATUS_NORMAL)
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * gtk_print_job_get_surface:
+ * @job: a `GtkPrintJob`
+ * @error: (nullable): return location for errors
+ *
+ * Gets a cairo surface onto which the pages of
+ * the print job should be rendered.
+ *
+ * Returns: (transfer none): the cairo surface of @job
+ */
+cairo_surface_t *
+gtk_print_job_get_surface (GtkPrintJob  *job,
+                          GError      **error)
+{
+  char *filename = NULL;
+  double width, height;
+  GtkPaperSize *paper_size;
+  int fd;
+  GError *tmp_error;
+
+  tmp_error = NULL;
+
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
+
+  if (job->surface)
+    return job->surface;
+  g_return_val_if_fail (job->spool_io == NULL, NULL);
+  fd = g_file_open_tmp ("gtkprint_XXXXXX", 
+                        &filename, 
+                        &tmp_error);
+  if (fd == -1)
+    {
+      g_free (filename);
+      g_propagate_error (error, tmp_error);
+      return NULL;
+    }
+
+  fchmod (fd, S_IRUSR | S_IWUSR);
+  
+#ifdef G_ENABLE_DEBUG
+  /* If we are debugging printing don't delete the tmp files */
+  if (GTK_DEBUG_CHECK (PRINTING)) ;
+  else
+#endif /* G_ENABLE_DEBUG */
+  g_unlink (filename);
+  g_free (filename);
+
+  paper_size = gtk_page_setup_get_paper_size (job->page_setup);
+  width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+  height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+  job->spool_io = g_io_channel_unix_new (fd);
+  g_io_channel_set_close_on_unref (job->spool_io, TRUE);
+  g_io_channel_set_encoding (job->spool_io, NULL, &tmp_error);
+  
+  if (tmp_error != NULL)
+    {
+      g_io_channel_unref (job->spool_io);
+      job->spool_io = NULL;
+      g_propagate_error (error, tmp_error);
+      return NULL;
+    }
+
+  job->surface = _gtk_printer_create_cairo_surface (job->printer,
+                                                    job->settings,
+                                                    width, height,
+                                                    job->spool_io);
+  
+  return job->surface;
+}
+
+/**
+ * gtk_print_job_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
+ * @job: a `GtkPrintJob`
+ * @track_status: %TRUE to track status after printing
+ *
+ * If track_status is %TRUE, the print job will try to continue report
+ * on the status of the print job in the printer queues and printer.
+ *
+ * This can allow your application to show things like “out of paper”
+ * issues, and when the print job actually reaches the printer.
+ *
+ * This function is often implemented using some form of polling,
+ * so it should not be enabled unless needed.
+ */
+void
+gtk_print_job_set_track_print_status (GtkPrintJob *job,
+                                     gboolean     track_status)
+{
+  g_return_if_fail (GTK_IS_PRINT_JOB (job));
+
+  track_status = track_status != FALSE;
+
+  if (job->track_print_status != track_status)
+    {
+      job->track_print_status = track_status;
+      
+      g_object_notify (G_OBJECT (job), "track-print-status");
+    }
+}
+
+/**
+ * gtk_print_job_get_track_print_status: (attributes org.gtk.Method.get_property=track-print-status)
+ * @job: a `GtkPrintJob`
+ *
+ * Returns whether jobs will be tracked after printing.
+ *
+ * For details, see [method@Gtk.PrintJob.set_track_print_status].
+ *
+ * Returns: %TRUE if print job status will be reported after printing
+ */
+gboolean
+gtk_print_job_get_track_print_status (GtkPrintJob *job)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
+  
+  return job->track_print_status;
+}
+
+static void
+gtk_print_job_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                            GParamSpec   *pspec)
+
+{
+  GtkPrintJob *job = GTK_PRINT_JOB (object);
+  GtkPrintSettings *settings;
+
+  switch (prop_id)
+    {
+    case PROP_TITLE:
+      g_free (job->title);
+      job->title = g_value_dup_string (value);
+      break;
+    
+    case PROP_PRINTER:
+      job->printer = GTK_PRINTER (g_value_dup_object (value));
+      job->printer_set = TRUE;
+      job->backend = g_object_ref (gtk_printer_get_backend (job->printer));
+      break;
+
+    case PROP_PAGE_SETUP:
+      job->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
+      job->page_setup_set = TRUE;
+      break;
+      
+    case PROP_SETTINGS:
+      /* We save a copy of the settings since we modify
+       * if when preparing the printer job. */
+      settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
+      job->settings = gtk_print_settings_copy (settings);
+      job->settings_set = TRUE;
+      break;
+
+    case PROP_TRACK_PRINT_STATUS:
+      gtk_print_job_set_track_print_status (job, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_print_job_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  GtkPrintJob *job = GTK_PRINT_JOB (object);
+
+  switch (prop_id)
+    {
+    case PROP_TITLE:
+      g_value_set_string (value, job->title);
+      break;
+    case PROP_PRINTER:
+      g_value_set_object (value, job->printer);
+      break;
+    case PROP_SETTINGS:
+      g_value_set_object (value, job->settings);
+      break;
+    case PROP_PAGE_SETUP:
+      g_value_set_object (value, job->page_setup);
+      break;
+    case PROP_TRACK_PRINT_STATUS:
+      g_value_set_boolean (value, job->track_print_status);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_print_job_send:
+ * @job: a `GtkPrintJob`
+ * @callback: function to call when the job completes or an error occurs
+ * @user_data: (closure): user data that gets passed to @callback
+ * @dnotify: destroy notify for @user_data
+ *
+ * Sends the print job off to the printer.
+ */
+void
+gtk_print_job_send (GtkPrintJob             *job,
+                    GtkPrintJobCompleteFunc  callback,
+                    gpointer                 user_data,
+                   GDestroyNotify           dnotify)
+{
+  g_return_if_fail (GTK_IS_PRINT_JOB (job));
+  g_return_if_fail (job->spool_io != NULL);
+  
+  gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
+  
+  g_io_channel_seek_position (job->spool_io, 0, G_SEEK_SET, NULL);
+  
+  gtk_print_backend_print_stream (job->backend, job,
+                                 job->spool_io,
+                                  callback, user_data, dnotify);
+}
+
+/**
+ * gtk_print_job_get_pages:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPrintPages` setting for this job.
+ *
+ * Returns: the `GtkPrintPages` setting
+ */
+GtkPrintPages
+gtk_print_job_get_pages (GtkPrintJob *job)
+{
+  return job->print_pages;
+}
+
+/**
+ * gtk_print_job_set_pages:
+ * @job: a `GtkPrintJob`
+ * @pages: the `GtkPrintPages` setting
+ *
+ * Sets the `GtkPrintPages` setting for this job.
+ */
+void
+gtk_print_job_set_pages (GtkPrintJob   *job,
+                         GtkPrintPages  pages)
+{
+  job->print_pages = pages;
+}
+
+/**
+ * gtk_print_job_get_page_ranges:
+ * @job: a `GtkPrintJob`
+ * @n_ranges: (out): return location for the number of ranges
+ *
+ * Gets the page ranges for this job.
+ *
+ * Returns: (array length=n_ranges) (transfer none): a pointer to an
+ *   array of `GtkPageRange` structs
+ */
+GtkPageRange *
+gtk_print_job_get_page_ranges (GtkPrintJob *job,
+                               int         *n_ranges)
+{
+  *n_ranges = job->num_page_ranges;
+  return job->page_ranges;
+}
+
+/**
+ * gtk_print_job_set_page_ranges:
+ * @job: a `GtkPrintJob`
+ * @ranges: (array length=n_ranges) (transfer full): pointer to an array of
+ *    `GtkPageRange` structs
+ * @n_ranges: the length of the @ranges array
+ *
+ * Sets the page ranges for this job.
+ */
+void
+gtk_print_job_set_page_ranges (GtkPrintJob  *job,
+                               GtkPageRange *ranges,
+                               int           n_ranges)
+{
+  g_free (job->page_ranges);
+  job->page_ranges = ranges;
+  job->num_page_ranges = n_ranges;
+}
+
+/**
+ * gtk_print_job_get_page_set:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the `GtkPageSet` setting for this job.
+ *
+ * Returns: the `GtkPageSet` setting
+ */
+GtkPageSet
+gtk_print_job_get_page_set (GtkPrintJob *job)
+{
+  return job->page_set;
+}
+
+/**
+ * gtk_print_job_set_page_set:
+ * @job: a `GtkPrintJob`
+ * @page_set: a `GtkPageSet` setting
+ *
+ * Sets the `GtkPageSet` setting for this job.
+ */
+void
+gtk_print_job_set_page_set (GtkPrintJob *job,
+                            GtkPageSet   page_set)
+{
+  job->page_set = page_set;
+}
+
+/**
+ * gtk_print_job_get_num_copies:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the number of copies of this job.
+ *
+ * Returns: the number of copies
+ */
+int
+gtk_print_job_get_num_copies (GtkPrintJob *job)
+{
+  return job->num_copies;
+}
+
+/**
+ * gtk_print_job_set_num_copies:
+ * @job: a `GtkPrintJob`
+ * @num_copies: the number of copies
+ *
+ * Sets the number of copies for this job.
+ */
+void
+gtk_print_job_set_num_copies (GtkPrintJob *job,
+                              int          num_copies)
+{
+  job->num_copies = num_copies;
+}
+
+/**
+ * gtk_print_job_get_scale:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the scale for this job.
+ *
+ * Returns: the scale
+ */
+double
+gtk_print_job_get_scale (GtkPrintJob *job)
+
+{
+  return job->scale;
+}
+
+/**
+ * gtk_print_job_set_scale:
+ * @job: a `GtkPrintJob`
+ * @scale: the scale
+ *
+ * Sets the scale for this job.
+ *
+ * 1.0 means unscaled.
+ */
+void
+gtk_print_job_set_scale (GtkPrintJob *job,
+                         double       scale)
+{
+  job->scale = scale;
+}
+
+/**
+ * gtk_print_job_get_n_up:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the n-up setting for this job.
+ *
+ * Returns: the n-up setting
+ */
+guint
+gtk_print_job_get_n_up (GtkPrintJob *job)
+{
+  return job->number_up;
+}
+
+/**
+ * gtk_print_job_set_n_up:
+ * @job: a `GtkPrintJob`
+ * @n_up: the n-up value
+ *
+ * Sets the n-up setting for this job.
+ */
+void
+gtk_print_job_set_n_up (GtkPrintJob *job,
+                        guint        n_up)
+{
+  job->number_up = n_up;
+}
+
+/**
+ * gtk_print_job_get_n_up_layout:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets the n-up layout setting for this job.
+ *
+ * Returns: the n-up layout
+ */
+GtkNumberUpLayout
+gtk_print_job_get_n_up_layout (GtkPrintJob *job)
+{
+  return job->number_up_layout;
+}
+
+/**
+ * gtk_print_job_set_n_up_layout:
+ * @job: a `GtkPrintJob`
+ * @layout: the n-up layout setting
+ *
+ * Sets the n-up layout setting for this job.
+ */
+void
+gtk_print_job_set_n_up_layout (GtkPrintJob       *job,
+                               GtkNumberUpLayout  layout)
+{
+  job->number_up_layout = layout;
+}
+
+/**
+ * gtk_print_job_get_rotate:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether the job is printed rotated.
+ *
+ * Returns: whether the job is printed rotated
+ */
+gboolean
+gtk_print_job_get_rotate (GtkPrintJob *job)
+{
+  return job->rotate_to_orientation;
+}
+
+/**
+ * gtk_print_job_set_rotate:
+ * @job: a `GtkPrintJob`
+ * @rotate: whether to print rotated
+ *
+ * Sets whether this job is printed rotated.
+ */
+void
+gtk_print_job_set_rotate (GtkPrintJob *job,
+                          gboolean     rotate)
+{
+  job->rotate_to_orientation = rotate;
+}
+
+/**
+ * gtk_print_job_get_collate:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether this job is printed collated.
+ *
+ * Returns: whether the job is printed collated
+ */
+gboolean
+gtk_print_job_get_collate (GtkPrintJob *job)
+{
+  return job->collate;
+}
+
+/**
+ * gtk_print_job_set_collate:
+ * @job: a `GtkPrintJob`
+ * @collate: whether the job is printed collated
+ *
+ * Sets whether this job is printed collated.
+ */
+void
+gtk_print_job_set_collate (GtkPrintJob *job,
+                           gboolean     collate)
+{
+  job->collate = collate;
+}
+
+/**
+ * gtk_print_job_get_reverse:
+ * @job: a `GtkPrintJob`
+ *
+ * Gets whether this job is printed reversed.
+ *
+ * Returns: whether the job is printed reversed.
+ */
+gboolean
+gtk_print_job_get_reverse (GtkPrintJob *job)
+{
+  return job->reverse;
+}
+
+/**
+ * gtk_print_job_set_reverse:
+ * @job: a `GtkPrintJob`
+ * @reverse: whether the job is printed reversed
+ *
+ * Sets whether this job is printed reversed.
+ */
+void
+gtk_print_job_set_reverse (GtkPrintJob *job,
+                           gboolean     reverse)
+{
+  job->reverse = reverse;
+}
diff --git a/gtk/print/gtkprintjob.h b/gtk/print/gtkprintjob.h
new file mode 100644 (file)
index 0000000..f153424
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <cairo.h>
+
+#include <gtk/gtk.h>
+#include <gtk/print/gtkprinter.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_JOB                  (gtk_print_job_get_type ())
+#define GTK_PRINT_JOB(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_JOB, GtkPrintJob))
+#define GTK_IS_PRINT_JOB(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_JOB))
+
+typedef struct _GtkPrintJob          GtkPrintJob;
+
+/**
+ * GtkPrintJobCompleteFunc:
+ * @print_job: the `GtkPrintJob`
+ * @user_data: user data that has been passed to gtk_print_job_send()
+ * @error: a `GError` that contains error information if the sending
+ *   of the print job failed, otherwise %NULL
+ *
+ * The type of callback that is passed to gtk_print_job_send().
+ *
+ * It is called when the print job has been completely sent.
+ */
+typedef void (*GtkPrintJobCompleteFunc) (GtkPrintJob  *print_job,
+                                         gpointer      user_data,
+                                         const GError *error);
+
+
+GDK_AVAILABLE_IN_ALL
+GType                    gtk_print_job_get_type               (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkPrintJob             *gtk_print_job_new                    (const char               *title,
+                                                              GtkPrinter               *printer,
+                                                              GtkPrintSettings         *settings,
+                                                              GtkPageSetup             *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings        *gtk_print_job_get_settings           (GtkPrintJob              *job);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter              *gtk_print_job_get_printer            (GtkPrintJob              *job);
+GDK_AVAILABLE_IN_ALL
+const char *            gtk_print_job_get_title              (GtkPrintJob              *job);
+GDK_AVAILABLE_IN_ALL
+GtkPrintStatus           gtk_print_job_get_status             (GtkPrintJob              *job);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_print_job_set_source_file        (GtkPrintJob              *job,
+                                                              const char               *filename,
+                                                              GError                  **error);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_print_job_set_source_fd          (GtkPrintJob              *job,
+                                                              int                       fd,
+                                                              GError                  **error);
+GDK_AVAILABLE_IN_ALL
+cairo_surface_t         *gtk_print_job_get_surface            (GtkPrintJob              *job,
+                                                              GError                  **error);
+GDK_AVAILABLE_IN_ALL
+void                     gtk_print_job_set_track_print_status (GtkPrintJob              *job,
+                                                              gboolean                  track_status);
+GDK_AVAILABLE_IN_ALL
+gboolean                 gtk_print_job_get_track_print_status (GtkPrintJob              *job);
+GDK_AVAILABLE_IN_ALL
+void                     gtk_print_job_send                   (GtkPrintJob              *job,
+                                                              GtkPrintJobCompleteFunc   callback,
+                                                              gpointer                  user_data,
+                                                              GDestroyNotify            dnotify);
+
+GDK_AVAILABLE_IN_ALL
+GtkPrintPages     gtk_print_job_get_pages       (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_pages       (GtkPrintJob       *job,
+                                                 GtkPrintPages      pages);
+GDK_AVAILABLE_IN_ALL
+GtkPageRange *    gtk_print_job_get_page_ranges (GtkPrintJob       *job,
+                                                 int               *n_ranges);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_page_ranges (GtkPrintJob       *job,
+                                                 GtkPageRange      *ranges,
+                                                 int                n_ranges);
+GDK_AVAILABLE_IN_ALL
+GtkPageSet        gtk_print_job_get_page_set    (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_page_set    (GtkPrintJob       *job,
+                                                 GtkPageSet         page_set);
+GDK_AVAILABLE_IN_ALL
+int               gtk_print_job_get_num_copies  (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_num_copies  (GtkPrintJob       *job,
+                                                 int                num_copies);
+GDK_AVAILABLE_IN_ALL
+double            gtk_print_job_get_scale       (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_scale       (GtkPrintJob       *job,
+                                                 double             scale);
+GDK_AVAILABLE_IN_ALL
+guint             gtk_print_job_get_n_up        (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_n_up        (GtkPrintJob       *job,
+                                                 guint              n_up);
+GDK_AVAILABLE_IN_ALL
+GtkNumberUpLayout gtk_print_job_get_n_up_layout (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_n_up_layout (GtkPrintJob       *job,
+                                                 GtkNumberUpLayout  layout);
+GDK_AVAILABLE_IN_ALL
+gboolean          gtk_print_job_get_rotate      (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_rotate      (GtkPrintJob       *job,
+                                                 gboolean           rotate);
+GDK_AVAILABLE_IN_ALL
+gboolean          gtk_print_job_get_collate     (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_collate     (GtkPrintJob       *job,
+                                                 gboolean           collate);
+GDK_AVAILABLE_IN_ALL
+gboolean          gtk_print_job_get_reverse     (GtkPrintJob       *job);
+GDK_AVAILABLE_IN_ALL
+void              gtk_print_job_set_reverse     (GtkPrintJob       *job,
+                                                 gboolean           reverse);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintJob, g_object_unref)
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprintoperation-portal.c b/gtk/print/gtkprintoperation-portal.c
new file mode 100644 (file)
index 0000000..d39ad16
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
+
+#include <gio/gunixfdlist.h>
+
+#include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
+#include "gtkprintsettings.h"
+#include "gtkpagesetup.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkfilelauncher.h"
+#include <glib/gi18n-lib.h>
+#include "gtkwindowprivate.h"
+#include "gtkprivate.h"
+
+
+typedef struct {
+  GtkPrintOperation *op;
+  GDBusProxy *proxy;
+  guint response_signal_id;
+  gboolean do_print;
+  GtkPrintOperationResult result;
+  GtkPrintOperationPrintFunc print_cb;
+  GtkWindow *parent;
+  char *handle;
+  GMainLoop *loop;
+  guint32 token;
+  GDestroyNotify destroy;
+  GVariant *settings;
+  GVariant *setup;
+  GVariant *options;
+  char *prepare_print_handle;
+} PortalData;
+
+static void
+portal_data_free (gpointer data)
+{
+  PortalData *portal = data;
+
+  if (portal->parent && portal->handle)
+    gtk_window_unexport_handle (portal->parent, portal->handle);
+  g_free (portal->handle);
+  g_object_unref (portal->op);
+  g_object_unref (portal->proxy);
+  if (portal->loop)
+    g_main_loop_unref (portal->loop);
+  if (portal->settings)
+    g_variant_unref (portal->settings);
+  if (portal->setup)
+    g_variant_unref (portal->setup);
+  if (portal->options)
+    g_variant_unref (portal->options);
+  g_free (portal->prepare_print_handle);
+  g_free (portal);
+}
+
+typedef struct {
+  GDBusProxy *proxy;
+  GtkPrintJob *job;
+  guint32 token;
+  cairo_surface_t *surface;
+  GMainLoop *loop;
+  gboolean file_written;
+} GtkPrintOperationPortal;
+
+static void
+op_portal_free (GtkPrintOperationPortal *op_portal)
+{
+  g_clear_object (&op_portal->proxy);
+  g_clear_object (&op_portal->job);
+  if (op_portal->loop)
+    g_main_loop_unref (op_portal->loop);
+  g_free (op_portal);
+}
+
+static void
+portal_start_page (GtkPrintOperation *op,
+                   GtkPrintContext   *print_context,
+                   GtkPageSetup      *page_setup)
+{
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GtkPaperSize *paper_size;
+  cairo_surface_type_t type;
+  double w, h;
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+  type = cairo_surface_get_type (op_portal->surface);
+
+  if ((op->priv->manual_number_up < 2) ||
+      (op->priv->page_position % op->priv->manual_number_up == 0))
+    {
+      if (type == CAIRO_SURFACE_TYPE_PS)
+        {
+          cairo_ps_surface_set_size (op_portal->surface, w, h);
+          cairo_ps_surface_dsc_begin_page_setup (op_portal->surface);
+          switch (gtk_page_setup_get_orientation (page_setup))
+            {
+              case GTK_PAGE_ORIENTATION_PORTRAIT:
+              case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+                cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Portrait");
+                break;
+
+              case GTK_PAGE_ORIENTATION_LANDSCAPE:
+              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+                cairo_ps_surface_dsc_comment (op_portal->surface, "%%PageOrientation: Landscape");
+                break;
+
+              default:
+                break;
+            }
+         }
+      else if (type == CAIRO_SURFACE_TYPE_PDF)
+        {
+          if (!op->priv->manual_orientation)
+            {
+              w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+              h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+            }
+          cairo_pdf_surface_set_size (op_portal->surface, w, h);
+        }
+    }
+}
+
+static void
+portal_end_page (GtkPrintOperation *op,
+                 GtkPrintContext   *print_context)
+{
+  cairo_t *cr;
+
+  cr = gtk_print_context_get_cairo_context (print_context);
+
+  if ((op->priv->manual_number_up < 2) ||
+      ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
+      (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
+    cairo_show_page (cr);
+}
+
+static void
+print_file_done (GObject *source,
+                 GAsyncResult *result,
+                 gpointer data)
+{
+  GtkPrintOperation *op = data;
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GError *error = NULL;
+  GVariant *ret;
+
+  ret = g_dbus_proxy_call_finish (op_portal->proxy,
+                                  result,
+                                  &error);
+  if (ret == NULL)
+    {
+      if (op->priv->error == NULL)
+        op->priv->error = g_error_copy (error);
+      g_warning ("Print file failed: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    g_variant_unref (ret);
+
+  if (op_portal->loop)
+    g_main_loop_quit (op_portal->loop);
+
+  g_object_unref (op);
+}
+
+static void
+portal_job_complete (GtkPrintJob  *job,
+                     gpointer      data,
+                     const GError *error)
+{
+  GtkPrintOperation *op = data;
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+  GtkPrintSettings *settings;
+  const char *uri;
+  char *filename;
+  int fd, idx;
+  GVariantBuilder opt_builder;
+  GUnixFDList *fd_list;
+
+  if (error != NULL && op->priv->error == NULL)
+    {
+      g_warning ("Print job failed: %s", error->message);
+      op->priv->error = g_error_copy (error);
+      return;
+    }
+
+  op_portal->file_written = TRUE;
+
+  settings = gtk_print_job_get_settings (job);
+  uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
+  filename = g_filename_from_uri (uri, NULL, NULL);
+
+  fd = open (filename, O_RDONLY|O_CLOEXEC);
+  fd_list = g_unix_fd_list_new ();
+  idx = g_unix_fd_list_append (fd_list, fd, NULL);
+  close (fd);
+
+  g_free (filename);
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+  g_variant_builder_add (&opt_builder, "{sv}",  "token", g_variant_new_uint32 (op_portal->token));
+
+  g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy,
+                                       "Print",
+                                       g_variant_new ("(ssh@a{sv})",
+                                                      "", /* window */
+                                                      _("Print"), /* title */
+                                                      idx,
+                                                      g_variant_builder_end (&opt_builder)),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       fd_list,
+                                       NULL,
+                                       print_file_done,
+                                       op);
+  g_object_unref (fd_list);
+}
+
+static void
+portal_end_run (GtkPrintOperation *op,
+                gboolean           wait,
+                gboolean           cancelled)
+{
+  GtkPrintOperationPortal *op_portal = op->priv->platform_data;
+
+  cairo_surface_finish (op_portal->surface);
+
+  if (cancelled)
+    return;
+
+  if (wait)
+    op_portal->loop = g_main_loop_new (NULL, FALSE);
+
+  /* TODO: Check for error */
+  if (op_portal->job != NULL)
+    {
+      g_object_ref (op);
+      gtk_print_job_send (op_portal->job, portal_job_complete, op, NULL);
+    }
+
+  if (wait)
+    {
+      g_object_ref (op);
+      if (!op_portal->file_written)
+        g_main_loop_run (op_portal->loop);
+      g_object_unref (op);
+    }
+}
+
+static void
+finish_print (PortalData        *portal,
+              GtkPrinter        *printer,
+              GtkPageSetup      *page_setup,
+              GtkPrintSettings  *settings)
+{
+  GtkPrintOperation *op = portal->op;
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPrintJob *job;
+  GtkPrintOperationPortal *op_portal;
+  cairo_t *cr;
+
+  if (portal->do_print)
+    {
+      gtk_print_operation_set_print_settings (op, settings);
+      priv->print_context = _gtk_print_context_new (op);
+
+      _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
+
+      gtk_print_operation_set_default_page_setup (op, page_setup);
+      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+
+      op_portal = g_new0 (GtkPrintOperationPortal, 1);
+      priv->platform_data = op_portal;
+      priv->free_platform_data = (GDestroyNotify) op_portal_free;
+
+      priv->start_page = portal_start_page;
+      priv->end_page = portal_end_page;
+      priv->end_run = portal_end_run;
+
+      job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
+      op_portal->job = job;
+
+      op_portal->proxy = g_object_ref (portal->proxy);
+      op_portal->token = portal->token;
+
+      op_portal->surface = gtk_print_job_get_surface (job, &priv->error);
+      if (op_portal->surface == NULL)
+        {
+          portal->result = GTK_PRINT_OPERATION_RESULT_ERROR;
+          portal->do_print = FALSE;
+          goto out;
+        }
+
+      cr = cairo_create (op_portal->surface);
+      gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
+      cairo_destroy (cr);
+
+      priv->print_pages = gtk_print_job_get_pages (job);
+      priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
+      priv->manual_num_copies = gtk_print_job_get_num_copies (job);
+      priv->manual_collation = gtk_print_job_get_collate (job);
+      priv->manual_reverse = gtk_print_job_get_reverse (job);
+      priv->manual_page_set = gtk_print_job_get_page_set (job);
+      priv->manual_scale = gtk_print_job_get_scale (job);
+      priv->manual_orientation = gtk_print_job_get_rotate (job);
+      priv->manual_number_up = gtk_print_job_get_n_up (job);
+      priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
+    }
+
+out:
+  if (portal->print_cb)
+    portal->print_cb (op, portal->parent, portal->do_print, portal->result);
+
+  if (portal->destroy)
+    portal->destroy (portal);
+}
+
+static GtkPrinter *
+find_file_printer (void)
+{
+  GList *backends, *l, *printers;
+  GtkPrinter *printer;
+
+  printer = NULL;
+
+  backends = gtk_print_backend_load_modules ();
+  for (l = backends; l; l = l->next)
+    {
+      GtkPrintBackend *backend = l->data;
+      if (strcmp (G_OBJECT_TYPE_NAME (backend), "GtkPrintBackendFile") == 0)
+        {
+          printers = gtk_print_backend_get_printer_list (backend);
+          printer = printers->data;
+          g_list_free (printers);
+          break;
+        }
+    }
+  g_list_free (backends);
+
+  return printer;
+}
+
+static void
+prepare_print_response (GDBusConnection *connection,
+                        const char      *sender_name,
+                        const char      *object_path,
+                        const char      *interface_name,
+                        const char      *signal_name,
+                        GVariant        *parameters,
+                        gpointer         data)
+{
+  PortalData *portal = data;
+  guint32 response;
+  GVariant *options = NULL;
+
+  if (portal->response_signal_id != 0)
+    {
+      g_dbus_connection_signal_unsubscribe (connection,
+                                            portal->response_signal_id);
+      portal->response_signal_id = 0;
+    }
+
+  g_variant_get (parameters, "(u@a{sv})", &response, &options);
+
+  portal->do_print = (response == 0);
+
+  if (portal->do_print)
+    {
+      GVariant *v;
+      GtkPrintSettings *settings;
+      GtkPageSetup *page_setup;
+      GtkPrinter *printer;
+      char *filename;
+      char *uri;
+      int fd;
+
+      portal->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      v = g_variant_lookup_value (options, "settings", G_VARIANT_TYPE_VARDICT);
+      settings = gtk_print_settings_new_from_gvariant (v);
+      g_variant_unref (v);
+
+      v = g_variant_lookup_value (options, "page-setup", G_VARIANT_TYPE_VARDICT);
+      page_setup = gtk_page_setup_new_from_gvariant (v);
+      g_variant_unref (v);
+
+      g_variant_lookup (options, "token", "u", &portal->token);
+
+      printer = find_file_printer ();
+
+      fd = g_file_open_tmp ("gtkprintXXXXXX", &filename, NULL);
+      uri = g_filename_to_uri (filename, NULL, NULL);
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
+      g_free (uri);
+      close (fd);
+
+      finish_print (portal, printer, page_setup, settings);
+      g_free (filename);
+    }
+  else
+    {
+      portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+
+      if (portal->print_cb)
+        portal->print_cb (portal->op, portal->parent, portal->do_print, portal->result);
+
+      if (portal->destroy)
+        portal->destroy (portal);
+    }
+
+  if (options)
+    g_variant_unref (options);
+
+  if (portal->loop)
+    g_main_loop_quit (portal->loop);
+}
+
+static void
+prepare_print_called (GObject      *source,
+                      GAsyncResult *result,
+                      gpointer      data)
+{
+  PortalData *portal = data;
+  GError *error = NULL;
+  const char *handle = NULL;
+  GVariant *ret;
+
+  ret = g_dbus_proxy_call_finish (portal->proxy, result, &error);
+  if (ret == NULL)
+    {
+      if (portal->op->priv->error == NULL)
+        portal->op->priv->error = g_error_copy (error);
+      g_error_free (error);
+      if (portal->loop)
+        g_main_loop_quit (portal->loop);
+      return;
+    }
+  else
+    g_variant_get (ret, "(&o)", &handle);
+
+  if (strcmp (portal->prepare_print_handle, handle) != 0)
+    {
+      g_free (portal->prepare_print_handle);
+      portal->prepare_print_handle = g_strdup (handle);
+      g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                            portal->response_signal_id);
+      portal->response_signal_id =
+        g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                            PORTAL_BUS_NAME,
+                                            PORTAL_REQUEST_INTERFACE,
+                                            "Response",
+                                            handle,
+                                            NULL,
+                                            G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                            prepare_print_response,
+                                            portal, NULL);
+     }
+
+  g_variant_unref (ret);
+}
+
+static PortalData *
+create_portal_data (GtkPrintOperation          *op,
+                    GtkWindow                  *parent,
+                    GtkPrintOperationPrintFunc  print_cb)
+{
+  GDBusProxy *proxy;
+  PortalData *portal;
+  guint signal_id;
+  GError *error = NULL;
+
+  signal_id = g_signal_lookup ("create-custom-widget", GTK_TYPE_PRINT_OPERATION);
+  if (g_signal_has_handler_pending (op, signal_id, 0, TRUE))
+    g_warning ("GtkPrintOperation::create-custom-widget not supported with portal");
+
+  proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                         G_DBUS_PROXY_FLAGS_NONE,
+                                         NULL,
+                                         PORTAL_BUS_NAME,
+                                         PORTAL_OBJECT_PATH,
+                                         PORTAL_PRINT_INTERFACE,
+                                         NULL,
+                                         &error);
+
+  if (proxy == NULL)
+    {
+      if (op->priv->error == NULL)
+        op->priv->error = g_error_copy (error);
+      g_error_free (error);
+      return NULL;
+    }
+
+  portal = g_new0 (PortalData, 1);
+  portal->proxy = proxy;
+  portal->op = g_object_ref (op);
+  portal->parent = parent;
+  portal->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  portal->print_cb = print_cb;
+
+  if (print_cb) /* async case */
+    {
+      portal->loop = NULL;
+      portal->destroy = portal_data_free;
+    }
+  else
+    {
+      portal->loop = g_main_loop_new (NULL, FALSE);
+      portal->destroy = NULL;
+    }
+
+  return portal;
+}
+
+static void
+window_handle_exported (GtkWindow  *window,
+                        const char *handle_str,
+                        gpointer    user_data)
+{
+  PortalData *portal = user_data;
+
+  portal->handle = g_strdup (handle_str);
+
+  g_dbus_proxy_call (portal->proxy,
+                     "PreparePrint",
+                     g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
+                                    handle_str,
+                                    _("Print"), /* title */
+                                    portal->settings,
+                                    portal->setup,
+                                    portal->options),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     prepare_print_called,
+                     portal);
+}
+
+static void
+call_prepare_print (GtkPrintOperation *op,
+                    PortalData        *portal)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GVariantBuilder opt_builder;
+  char *token;
+
+  portal->prepare_print_handle =
+      gtk_get_portal_request_path (g_dbus_proxy_get_connection (portal->proxy), &token);
+
+  portal->response_signal_id =
+    g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                        PORTAL_BUS_NAME,
+                                        PORTAL_REQUEST_INTERFACE,
+                                        "Response",
+                                        portal->prepare_print_handle,
+                                        NULL,
+                                        G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                        prepare_print_response,
+                                        portal, NULL);
+
+  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+  g_variant_builder_add (&opt_builder, "{sv}", "handle_token", g_variant_new_string (token));
+  g_free (token);
+  portal->options = g_variant_builder_end (&opt_builder);
+
+  if (priv->print_settings)
+    portal->settings = gtk_print_settings_to_gvariant (priv->print_settings);
+  else
+    {
+      GVariantBuilder builder;
+      g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+      portal->settings = g_variant_builder_end (&builder);
+    }
+
+  if (priv->default_page_setup)
+    portal->setup = gtk_page_setup_to_gvariant (priv->default_page_setup);
+  else
+    {
+      GtkPageSetup *page_setup = gtk_page_setup_new ();
+      portal->setup = gtk_page_setup_to_gvariant (page_setup);
+      g_object_unref (page_setup);
+    }
+
+  g_variant_ref_sink (portal->options);
+  g_variant_ref_sink (portal->settings);
+  g_variant_ref_sink (portal->setup);
+
+  if (portal->parent != NULL &&
+      gtk_widget_is_visible (GTK_WIDGET (portal->parent)) &&
+      gtk_window_export_handle (portal->parent, window_handle_exported, portal))
+    return;
+
+  g_dbus_proxy_call (portal->proxy,
+                     "PreparePrint",
+                     g_variant_new ("(ss@a{sv}@a{sv}@a{sv})",
+                                    "",
+                                    _("Print"), /* title */
+                                    portal->settings,
+                                    portal->setup,
+                                    portal->options),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     prepare_print_called,
+                     portal);
+}
+
+GtkPrintOperationResult
+gtk_print_operation_portal_run_dialog (GtkPrintOperation *op,
+                                       gboolean           show_dialog,
+                                       GtkWindow         *parent,
+                                       gboolean          *do_print)
+{
+  PortalData *portal;
+  GtkPrintOperationResult result;
+
+  portal = create_portal_data (op, parent, NULL);
+  if (portal == NULL)
+    return GTK_PRINT_OPERATION_RESULT_ERROR;
+
+  call_prepare_print (op, portal);
+
+  g_main_loop_run (portal->loop);
+
+  *do_print = portal->do_print;
+  result = portal->result;
+
+  portal_data_free (portal);
+
+  return result;
+}
+
+void
+gtk_print_operation_portal_run_dialog_async (GtkPrintOperation          *op,
+                                             gboolean                    show_dialog,
+                                             GtkWindow                  *parent,
+                                             GtkPrintOperationPrintFunc  print_cb)
+{
+  PortalData *portal;
+
+  portal = create_portal_data (op, parent, print_cb);
+  if (portal == NULL)
+    return;
+
+  call_prepare_print (op, portal);
+}
+
+void
+gtk_print_operation_portal_launch_preview (GtkPrintOperation *op,
+                                           cairo_surface_t   *surface,
+                                           GtkWindow         *parent,
+                                           const char        *filename)
+{
+  GFile *file;
+  GtkFileLauncher *launcher;
+
+  file = g_file_new_for_path (filename);
+  launcher = gtk_file_launcher_new (file);
+  gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
+  g_object_unref (launcher);
+  g_object_unref (file);
+}
diff --git a/gtk/print/gtkprintoperation-portal.h b/gtk/print/gtkprintoperation-portal.h
new file mode 100644 (file)
index 0000000..ee84b28
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "gtkprintoperation.h"
+
+G_BEGIN_DECLS
+
+GtkPrintOperationResult gtk_print_operation_portal_run_dialog             (GtkPrintOperation           *op,
+                                                                           gboolean                     show_dialog,
+                                                                           GtkWindow                   *parent,
+                                                                           gboolean                    *do_print);
+void                    gtk_print_operation_portal_run_dialog_async       (GtkPrintOperation           *op,
+                                                                           gboolean                     show_dialog,
+                                                                           GtkWindow                   *parent,
+                                                                           GtkPrintOperationPrintFunc   print_cb);
+void                    gtk_print_operation_portal_launch_preview         (GtkPrintOperation           *op,
+                                                                           cairo_surface_t             *surface,
+                                                                           GtkWindow                   *parent,
+                                                                           const char                  *filename);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprintoperation-private.h b/gtk/print/gtkprintoperation-private.h
new file mode 100644 (file)
index 0000000..46833a6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "gtkprintoperation.h"
+
+G_BEGIN_DECLS
+
+/* Page drawing states */
+typedef enum
+{
+  GTK_PAGE_DRAWING_STATE_READY,
+  GTK_PAGE_DRAWING_STATE_DRAWING,
+  GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING
+} GtkPageDrawingState;
+
+struct _GtkPrintOperationPrivate
+{
+  GtkPrintOperationAction action;
+  GtkPrintStatus status;
+  GError *error;
+  char *status_string;
+  GtkPageSetup *default_page_setup;
+  GtkPrintSettings *print_settings;
+  char *job_name;
+  int nr_of_pages;
+  int nr_of_pages_to_print;
+  int page_position;
+  int current_page;
+  GtkUnit unit;
+  char *export_filename;
+  guint use_full_page      : 1;
+  guint track_print_status : 1;
+  guint show_progress      : 1;
+  guint cancelled          : 1;
+  guint allow_async        : 1;
+  guint is_sync            : 1;
+  guint support_selection  : 1;
+  guint has_selection      : 1;
+  guint embed_page_setup   : 1;
+
+  GtkPageDrawingState      page_drawing_state;
+
+  guint print_pages_idle_id;
+  guint show_progress_timeout_id;
+
+  GtkPrintContext *print_context;
+  
+  GtkPrintPages print_pages;
+  GtkPageRange *page_ranges;
+  int num_page_ranges;
+  
+  int manual_num_copies;
+  guint manual_collation   : 1;
+  guint manual_reverse     : 1;
+  guint manual_orientation : 1;
+  double manual_scale;
+  GtkPageSet manual_page_set;
+  guint manual_number_up;
+  GtkNumberUpLayout manual_number_up_layout;
+
+  GtkWidget *custom_widget;
+  char *custom_tab_label;
+  
+  gpointer platform_data;
+  GDestroyNotify free_platform_data;
+
+  GMainLoop *rloop; /* recursive mainloop */
+
+  void (*start_page) (GtkPrintOperation *operation,
+                     GtkPrintContext   *print_context,
+                     GtkPageSetup      *page_setup);
+  void (*end_page)   (GtkPrintOperation *operation,
+                     GtkPrintContext   *print_context);
+  void (*end_run)    (GtkPrintOperation *operation,
+                     gboolean           wait,
+                     gboolean           cancelled);
+};
+
+
+typedef void (* GtkPrintOperationPrintFunc) (GtkPrintOperation      *op,
+                                            GtkWindow              *parent,
+                                            gboolean                do_print,
+                                            GtkPrintOperationResult result);
+
+GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog             (GtkPrintOperation           *operation,
+                                                                                     gboolean                     show_dialog,
+                                                                                     GtkWindow                   *parent,
+                                                                                     gboolean                    *do_print);
+void                    _gtk_print_operation_platform_backend_run_dialog_async       (GtkPrintOperation           *op,
+                                                                                     gboolean                     show_dialog,
+                                                                                     GtkWindow                   *parent,
+                                                                                     GtkPrintOperationPrintFunc   print_cb);
+void                    _gtk_print_operation_platform_backend_launch_preview         (GtkPrintOperation           *op,
+                                                                                     cairo_surface_t             *surface,
+                                                                                     GtkWindow                   *parent,
+                                                                                     const char                  *filename);
+cairo_surface_t *       _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation           *op,
+                                                                                     GtkPageSetup                *page_setup,
+                                                                                     double                      *dpi_x,
+                                                                                     double                      *dpi_y,
+                                                                                     char                        **target);
+void                    _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation           *op,
+                                                                                     GtkPageSetup                *page_setup,
+                                                                                     cairo_surface_t             *surface);
+void                    _gtk_print_operation_platform_backend_preview_start_page     (GtkPrintOperation *op,
+                                                                                     cairo_surface_t *surface,
+                                                                                     cairo_t *cr);
+void                    _gtk_print_operation_platform_backend_preview_end_page       (GtkPrintOperation *op,
+                                                                                     cairo_surface_t *surface,
+                                                                                     cairo_t *cr);
+
+void _gtk_print_operation_set_status (GtkPrintOperation *op,
+                                     GtkPrintStatus     status,
+                                     const char        *string);
+
+/* GtkPrintContext private functions: */
+
+GtkPrintContext *_gtk_print_context_new                             (GtkPrintOperation *op);
+void             _gtk_print_context_set_page_setup                  (GtkPrintContext   *context,
+                                                                    GtkPageSetup      *page_setup);
+void             _gtk_print_context_translate_into_margin           (GtkPrintContext   *context);
+void             _gtk_print_context_rotate_according_to_orientation (GtkPrintContext   *context);
+void             _gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context);
+void             _gtk_print_context_set_hard_margins                (GtkPrintContext   *context,
+                                                                    double             top,
+                                                                    double             bottom,
+                                                                    double             left,
+                                                                    double             right);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprintoperation-unix.c b/gtk/print/gtkprintoperation-unix.c
new file mode 100644 (file)
index 0000000..1108927
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <glib/gstdio.h>
+#include "gtkprintoperation-private.h"
+#include "gtkprintoperation-portal.h"
+
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
+#include "gtkprivate.h"
+#include "gtkprintunixdialog.h"
+#include "gtkpagesetupunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprinter.h"
+#include "gtkprintjob.h"
+#include "gtklabel.h"
+#include "gtkfilelauncher.h"
+#include <glib/gi18n-lib.h>
+
+
+typedef struct
+{
+  GtkWindow *parent;        /* just in case we need to throw error dialogs */
+  GMainLoop *loop;
+  gboolean data_sent;
+
+  /* Real printing (not preview) */
+  GtkPrintJob *job;         /* the job we are sending to the printer */
+  cairo_surface_t *surface;
+  gulong job_status_changed_tag;
+
+
+} GtkPrintOperationUnix;
+
+typedef struct _PrinterFinder PrinterFinder;
+
+static void printer_finder_free (PrinterFinder *finder);
+static void find_printer        (const char    *printer,
+                                GFunc          func,
+                                gpointer       data);
+
+static void
+unix_start_page (GtkPrintOperation *op,
+                GtkPrintContext   *print_context,
+                GtkPageSetup      *page_setup)
+{
+  GtkPrintOperationUnix *op_unix;
+  GtkPaperSize *paper_size;
+  cairo_surface_type_t type;
+  double w, h;
+
+  op_unix = op->priv->platform_data;
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+  type = cairo_surface_get_type (op_unix->surface);
+
+  if ((op->priv->manual_number_up < 2) ||
+      (op->priv->page_position % op->priv->manual_number_up == 0))
+    {
+      if (type == CAIRO_SURFACE_TYPE_PS)
+        {
+          cairo_ps_surface_set_size (op_unix->surface, w, h);
+          cairo_ps_surface_dsc_begin_page_setup (op_unix->surface);
+          switch (gtk_page_setup_get_orientation (page_setup))
+            {
+              case GTK_PAGE_ORIENTATION_PORTRAIT:
+              case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait");
+                break;
+
+              case GTK_PAGE_ORIENTATION_LANDSCAPE:
+              case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+                cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape");
+                break;
+              default:
+                break;
+            }
+         }
+      else if (type == CAIRO_SURFACE_TYPE_PDF)
+        {
+          if (!op->priv->manual_orientation)
+            {
+              w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+              h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+            }
+          cairo_pdf_surface_set_size (op_unix->surface, w, h);
+        }
+    }
+}
+
+static void
+unix_end_page (GtkPrintOperation *op,
+              GtkPrintContext   *print_context)
+{
+  cairo_t *cr;
+
+  cr = gtk_print_context_get_cairo_context (print_context);
+
+  if ((op->priv->manual_number_up < 2) ||
+      ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
+      (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
+    cairo_show_page (cr);
+}
+
+static void
+op_unix_free (GtkPrintOperationUnix *op_unix)
+{
+  if (op_unix->job)
+    {
+      if (op_unix->job_status_changed_tag > 0)
+        g_signal_handler_disconnect (op_unix->job,
+                                    op_unix->job_status_changed_tag);
+      g_object_unref (op_unix->job);
+    }
+
+  g_free (op_unix);
+}
+
+static char *
+shell_command_substitute_file (const char *cmd,
+                              const char *pdf_filename,
+                              const char *settings_filename,
+                               gboolean    *pdf_filename_replaced,
+                               gboolean    *settings_filename_replaced)
+{
+  const char *inptr, *start;
+  GString *final;
+
+  g_return_val_if_fail (cmd != NULL, NULL);
+  g_return_val_if_fail (pdf_filename != NULL, NULL);
+  g_return_val_if_fail (settings_filename != NULL, NULL);
+
+  final = g_string_new (NULL);
+
+  *pdf_filename_replaced = FALSE;
+  *settings_filename_replaced = FALSE;
+
+  start = inptr = cmd;
+  while ((inptr = strchr (inptr, '%')) != NULL)
+    {
+      g_string_append_len (final, start, inptr - start);
+      inptr++;
+      switch (*inptr)
+        {
+          case 'f':
+            g_string_append (final, pdf_filename);
+            *pdf_filename_replaced = TRUE;
+            break;
+
+          case 's':
+            g_string_append (final, settings_filename);
+            *settings_filename_replaced = TRUE;
+            break;
+
+          case '%':
+            g_string_append_c (final, '%');
+            break;
+
+          default:
+            g_string_append_c (final, '%');
+            if (*inptr)
+              g_string_append_c (final, *inptr);
+            break;
+        }
+      if (*inptr)
+        inptr++;
+      start = inptr;
+    }
+  g_string_append (final, start);
+
+  return g_string_free (final, FALSE);
+}
+
+static void
+gtk_print_operation_unix_launch_preview (GtkPrintOperation *op,
+                                         cairo_surface_t   *surface,
+                                         GtkWindow         *parent,
+                                         const char        *filename)
+{
+  GAppInfo *appinfo;
+  GdkAppLaunchContext *context;
+  char *cmd;
+  char *preview_cmd;
+  GtkSettings *settings;
+  GtkPrintSettings *print_settings = NULL;
+  GtkPageSetup *page_setup;
+  GKeyFile *key_file = NULL;
+  char *data = NULL;
+  gsize data_len;
+  char *settings_filename = NULL;
+  char *quoted_filename;
+  char *quoted_settings_filename;
+  gboolean filename_used = FALSE;
+  gboolean settings_used = FALSE;
+  GdkDisplay *display;
+  GError *error = NULL;
+  int fd;
+  gboolean retval;
+
+  cairo_surface_destroy (surface);
+
+  if (parent)
+    display = gtk_widget_get_display (GTK_WIDGET (parent));
+  else
+    display = gdk_display_get_default ();
+
+  fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error);
+  if (fd < 0)
+    goto out;
+
+  key_file = g_key_file_new ();
+
+  print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op));
+
+  if (print_settings != NULL)
+    {
+      gtk_print_settings_set_reverse (print_settings, FALSE);
+      gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL);
+      gtk_print_settings_set_scale (print_settings, 1.0);
+      gtk_print_settings_set_number_up (print_settings, 1);
+      gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
+
+      /*  These removals are necessary because cups-* settings have higher priority
+       *  than normal settings.
+       */
+      gtk_print_settings_unset (print_settings, "cups-reverse");
+      gtk_print_settings_unset (print_settings, "cups-page-set");
+      gtk_print_settings_unset (print_settings, "cups-scale");
+      gtk_print_settings_unset (print_settings, "cups-number-up");
+      gtk_print_settings_unset (print_settings, "cups-number-up-layout");
+
+      gtk_print_settings_to_key_file (print_settings, key_file, NULL);
+      g_object_unref (print_settings);
+    }
+
+  page_setup = gtk_print_context_get_page_setup (op->priv->print_context);
+  gtk_page_setup_to_key_file (page_setup, key_file, NULL);
+
+  g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name);
+
+  data = g_key_file_to_data (key_file, &data_len, &error);
+  if (!data)
+    goto out;
+
+  retval = g_file_set_contents (settings_filename, data, data_len, &error);
+  if (!retval)
+    goto out;
+
+  settings = gtk_settings_get_for_display (display);
+  g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);
+
+  quoted_filename = g_shell_quote (filename);
+  quoted_settings_filename = g_shell_quote (settings_filename);
+  cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used);
+
+  appinfo = g_app_info_create_from_commandline (cmd,
+                                                "Print Preview",
+                                                G_APP_INFO_CREATE_NONE,
+                                                &error);
+
+  g_free (preview_cmd);
+  g_free (quoted_filename);
+  g_free (quoted_settings_filename);
+  g_free (cmd);
+
+  if (error != NULL)
+    goto out;
+
+  context = gdk_display_get_app_launch_context (display);
+  g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error);
+
+  g_object_unref (context);
+  g_object_unref (appinfo);
+
+  if (error != NULL)
+    {
+      GFile *file;
+      GtkFileLauncher *launcher;
+
+      g_warning ("Error launching preview: %s", error->message);
+      g_clear_error (&error);
+
+      file = g_file_new_for_path (filename);
+      launcher = gtk_file_launcher_new (file);
+      gtk_file_launcher_launch (launcher, parent, NULL, NULL, NULL);
+      g_object_unref (launcher);
+      g_object_unref (file);
+    }
+
+ out:
+  if (error != NULL)
+    {
+      if (op->priv->error == NULL)
+        op->priv->error = error;
+      else
+        g_error_free (error);
+
+      filename_used = FALSE;
+      settings_used = FALSE;
+   }
+
+  if (!filename_used)
+    g_unlink (filename);
+
+  if (!settings_used)
+    g_unlink (settings_filename);
+
+  if (fd > 0)
+    close (fd);
+
+  if (key_file)
+    g_key_file_free (key_file);
+  g_free (data);
+  g_free (settings_filename);
+}
+
+static void
+unix_finish_send  (GtkPrintJob  *job,
+                   gpointer      user_data,
+                   const GError *error)
+{
+  GtkPrintOperation *op = (GtkPrintOperation *) user_data;
+  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
+
+  if (error != NULL && op->priv->error == NULL)
+    op->priv->error = g_error_copy (error);
+
+  op_unix->data_sent = TRUE;
+
+  if (op_unix->loop)
+    g_main_loop_quit (op_unix->loop);
+
+  g_object_unref (op);
+}
+
+static void
+unix_end_run (GtkPrintOperation *op,
+             gboolean           wait,
+             gboolean           cancelled)
+{
+  GtkPrintOperationUnix *op_unix = op->priv->platform_data;
+
+  cairo_surface_finish (op_unix->surface);
+
+  if (cancelled)
+    return;
+
+  if (wait)
+    op_unix->loop = g_main_loop_new (NULL, FALSE);
+
+  /* TODO: Check for error */
+  if (op_unix->job != NULL)
+    {
+      g_object_ref (op);
+      gtk_print_job_send (op_unix->job,
+                          unix_finish_send,
+                          op, NULL);
+    }
+
+  if (wait)
+    {
+      g_object_ref (op);
+      if (!op_unix->data_sent)
+       g_main_loop_run (op_unix->loop);
+      g_main_loop_unref (op_unix->loop);
+      op_unix->loop = NULL;
+      g_object_unref (op);
+    }
+}
+
+static void
+job_status_changed_cb (GtkPrintJob       *job,
+                      GtkPrintOperation *op)
+{
+  _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
+}
+
+
+static void
+print_setup_changed_cb (GtkPrintUnixDialog *print_dialog,
+                        GParamSpec         *pspec,
+                        gpointer            user_data)
+{
+  GtkPageSetup             *page_setup;
+  GtkPrintSettings         *print_settings;
+  GtkPrintOperation        *op = user_data;
+  GtkPrintOperationPrivate *priv = op->priv;
+
+  page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog);
+  print_settings = gtk_print_unix_dialog_get_settings (print_dialog);
+
+  g_signal_emit_by_name (op,
+                         "update-custom-widget",
+                         priv->custom_widget,
+                         page_setup,
+                         print_settings);
+}
+
+static GtkWidget *
+get_print_dialog (GtkPrintOperation *op,
+                  GtkWindow         *parent)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkWidget *pd, *label;
+  const char *custom_tab_label;
+
+  pd = gtk_print_unix_dialog_new (NULL, parent);
+
+  gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (pd),
+                                                GTK_PRINT_CAPABILITY_PAGE_SET |
+                                                GTK_PRINT_CAPABILITY_COPIES |
+                                                GTK_PRINT_CAPABILITY_COLLATE |
+                                                GTK_PRINT_CAPABILITY_REVERSE |
+                                                GTK_PRINT_CAPABILITY_SCALE |
+                                                GTK_PRINT_CAPABILITY_PREVIEW |
+                                                GTK_PRINT_CAPABILITY_NUMBER_UP |
+                                                GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT);
+
+  if (priv->print_settings)
+    gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
+                                       priv->print_settings);
+
+  if (priv->default_page_setup)
+    gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
+                                          priv->default_page_setup);
+
+  gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd),
+                                              priv->embed_page_setup);
+
+  gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd),
+                                          priv->current_page);
+
+  gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd),
+                                               priv->support_selection);
+
+  gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd),
+                                           priv->has_selection);
+
+  g_signal_emit_by_name (op, "create-custom-widget",
+                        &priv->custom_widget);
+
+  if (priv->custom_widget)
+    {
+      custom_tab_label = priv->custom_tab_label;
+
+      if (custom_tab_label == NULL)
+       {
+         custom_tab_label = g_get_application_name ();
+         if (custom_tab_label == NULL)
+           custom_tab_label = _("Application");
+       }
+
+      label = gtk_label_new (custom_tab_label);
+
+      gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd),
+                                           priv->custom_widget, label);
+
+      g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op);
+      g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op);
+    }
+
+  return pd;
+}
+
+typedef struct
+{
+  GtkPrintOperation           *op;
+  gboolean                     do_print;
+  gboolean                     do_preview;
+  GtkPrintOperationResult      result;
+  GtkPrintOperationPrintFunc   print_cb;
+  GDestroyNotify               destroy;
+  GtkWindow                   *parent;
+  GMainLoop                   *loop;
+} PrintResponseData;
+
+static void
+print_response_data_free (gpointer data)
+{
+  PrintResponseData *rdata = data;
+
+  g_object_unref (rdata->op);
+  g_free (rdata);
+}
+
+static void
+finish_print (PrintResponseData *rdata,
+             GtkPrinter        *printer,
+             GtkPageSetup      *page_setup,
+             GtkPrintSettings  *settings,
+             gboolean           page_setup_set)
+{
+  GtkPrintOperation *op = rdata->op;
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPrintJob *job;
+  double top, bottom, left, right;
+
+  if (rdata->do_print)
+    {
+      gtk_print_operation_set_print_settings (op, settings);
+      priv->print_context = _gtk_print_context_new (op);
+
+      if (gtk_print_settings_get_number_up (settings) < 2)
+        {
+         if (printer && (gtk_printer_get_hard_margins_for_paper_size (printer, gtk_page_setup_get_paper_size (page_setup), &top, &bottom, &left, &right) ||
+                         gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)))
+           _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right);
+       }
+      else
+        {
+         /* Pages do not have any unprintable area when printing n-up as each page on the
+          * sheet has been scaled down and translated to a position within the printable
+          * area of the sheet.
+          */
+         _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0);
+       }
+
+      if (page_setup != NULL &&
+          (gtk_print_operation_get_default_page_setup (op) == NULL ||
+           page_setup_set))
+        gtk_print_operation_set_default_page_setup (op, page_setup);
+
+      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+
+      if (!rdata->do_preview)
+        {
+         GtkPrintOperationUnix *op_unix;
+         cairo_t *cr;
+
+         op_unix = g_new0 (GtkPrintOperationUnix, 1);
+         priv->platform_data = op_unix;
+         priv->free_platform_data = (GDestroyNotify) op_unix_free;
+         op_unix->parent = rdata->parent;
+
+         priv->start_page = unix_start_page;
+         priv->end_page = unix_end_page;
+         priv->end_run = unix_end_run;
+
+         job = gtk_print_job_new (priv->job_name, printer, settings, page_setup);
+          op_unix->job = job;
+          gtk_print_job_set_track_print_status (job, priv->track_print_status);
+
+         op_unix->surface = gtk_print_job_get_surface (job, &priv->error);
+         if (op_unix->surface == NULL)
+            {
+             rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
+             rdata->do_print = FALSE;
+             goto out;
+            }
+
+         cr = cairo_create (op_unix->surface);
+         gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72);
+         cairo_destroy (cr);
+
+          _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
+
+          op_unix->job_status_changed_tag =
+           g_signal_connect (job, "status-changed",
+                             G_CALLBACK (job_status_changed_cb), op);
+
+          priv->print_pages = gtk_print_job_get_pages (job);
+          priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges);
+          priv->manual_num_copies = gtk_print_job_get_num_copies (job);
+          priv->manual_collation = gtk_print_job_get_collate (job);
+          priv->manual_reverse = gtk_print_job_get_reverse (job);
+          priv->manual_page_set = gtk_print_job_get_page_set (job);
+          priv->manual_scale = gtk_print_job_get_scale (job);
+          priv->manual_orientation = gtk_print_job_get_rotate (job);
+          priv->manual_number_up = gtk_print_job_get_n_up (job);
+          priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job);
+        }
+    }
+ out:
+  if (rdata->print_cb)
+    rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result);
+
+  if (rdata->destroy)
+    rdata->destroy (rdata);
+}
+
+static void
+handle_print_response (GtkWidget *dialog,
+                      int        response,
+                      gpointer   data)
+{
+  GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
+  PrintResponseData *rdata = data;
+  GtkPrintSettings *settings = NULL;
+  GtkPageSetup *page_setup = NULL;
+  GtkPrinter *printer = NULL;
+  gboolean page_setup_set = FALSE;
+
+  if (response == GTK_RESPONSE_OK)
+    {
+      printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
+
+      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+      rdata->do_preview = FALSE;
+      if (printer != NULL)
+       rdata->do_print = TRUE;
+    }
+  else if (response == GTK_RESPONSE_APPLY)
+    {
+      /* print preview */
+      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+      rdata->do_preview = TRUE;
+      rdata->do_print = TRUE;
+
+      rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
+    }
+
+  if (rdata->do_print)
+    {
+      settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
+      page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
+      page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd));
+
+      /* Set new print settings now so that custom-widget options
+       * can be added to the settings in the callback
+       */
+      gtk_print_operation_set_print_settings (rdata->op, settings);
+      g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget);
+    }
+
+  if (rdata->loop)
+    g_main_loop_quit (rdata->loop);
+
+  finish_print (rdata, printer, page_setup, settings, page_setup_set);
+
+  if (settings)
+    g_object_unref (settings);
+
+  gtk_window_destroy (GTK_WINDOW (pd));
+}
+
+
+static void
+found_printer (GtkPrinter        *printer,
+              PrintResponseData *rdata)
+{
+  GtkPrintOperation *op = rdata->op;
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPrintSettings *settings = NULL;
+  GtkPageSetup *page_setup = NULL;
+
+  if (rdata->loop)
+    g_main_loop_quit (rdata->loop);
+
+  if (printer != NULL)
+    {
+      rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      rdata->do_print = TRUE;
+
+      if (priv->print_settings)
+       settings = gtk_print_settings_copy (priv->print_settings);
+      else
+       settings = gtk_print_settings_new ();
+
+      gtk_print_settings_set_printer (settings,
+                                     gtk_printer_get_name (printer));
+
+      if (priv->default_page_setup)
+       page_setup = gtk_page_setup_copy (priv->default_page_setup);
+      else
+       page_setup = gtk_page_setup_new ();
+  }
+
+  finish_print (rdata, printer, page_setup, settings, FALSE);
+
+  if (settings)
+    g_object_unref (settings);
+
+  if (page_setup)
+    g_object_unref (page_setup);
+}
+
+static void
+gtk_print_operation_unix_run_dialog_async (GtkPrintOperation          *op,
+                                           gboolean                    show_dialog,
+                                           GtkWindow                  *parent,
+                                           GtkPrintOperationPrintFunc  print_cb)
+{
+  GtkWidget *pd;
+  PrintResponseData *rdata;
+  const char *printer_name;
+
+  rdata = g_new (PrintResponseData, 1);
+  rdata->op = g_object_ref (op);
+  rdata->do_print = FALSE;
+  rdata->do_preview = FALSE;
+  rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  rdata->print_cb = print_cb;
+  rdata->parent = parent;
+  rdata->loop = NULL;
+  rdata->destroy = print_response_data_free;
+
+  if (show_dialog)
+    {
+      pd = get_print_dialog (op, parent);
+      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
+
+      g_signal_connect (pd, "response",
+                       G_CALLBACK (handle_print_response), rdata);
+
+      gtk_window_present (GTK_WINDOW (pd));
+    }
+  else
+    {
+      printer_name = NULL;
+      if (op->priv->print_settings)
+       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+
+      find_printer (printer_name, (GFunc) found_printer, rdata);
+    }
+}
+
+static cairo_status_t
+write_preview (void                *closure,
+               const unsigned char *data,
+               unsigned int         length)
+{
+  int fd = GPOINTER_TO_INT (closure);
+  gssize written;
+
+  while (length > 0)
+    {
+      written = write (fd, data, length);
+
+      if (written == -1)
+       {
+         if (errno == EAGAIN || errno == EINTR)
+           continue;
+
+         return CAIRO_STATUS_WRITE_ERROR;
+       }
+
+      data += written;
+      length -= written;
+    }
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+close_preview (void *data)
+{
+  int fd = GPOINTER_TO_INT (data);
+
+  close (fd);
+}
+
+static cairo_surface_t *
+gtk_print_operation_unix_create_preview_surface (GtkPrintOperation *op,
+                                                 GtkPageSetup      *page_setup,
+                                                 double            *dpi_x,
+                                                 double            *dpi_y,
+                                                 char             **target)
+{
+  char *filename;
+  int fd;
+  GtkPaperSize *paper_size;
+  double w, h;
+  cairo_surface_t *surface;
+  static cairo_user_data_key_t key;
+
+  filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL);
+  fd = g_mkstemp (filename);
+
+  if (fd < 0)
+    {
+      g_free (filename);
+      return NULL;
+    }
+
+  *target = filename;
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
+  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+
+  *dpi_x = *dpi_y = 72;
+  surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h);
+
+  cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview);
+
+  return surface;
+}
+
+static void
+gtk_print_operation_unix_preview_start_page (GtkPrintOperation *op,
+                                             cairo_surface_t   *surface,
+                                             cairo_t           *cr)
+{
+}
+
+static void
+gtk_print_operation_unix_preview_end_page (GtkPrintOperation *op,
+                                           cairo_surface_t   *surface,
+                                           cairo_t           *cr)
+{
+  cairo_show_page (cr);
+}
+
+static void
+gtk_print_operation_unix_resize_preview_surface (GtkPrintOperation *op,
+                                                 GtkPageSetup      *page_setup,
+                                                 cairo_surface_t   *surface)
+{
+  double w, h;
+
+  w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+  h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+  cairo_pdf_surface_set_size (surface, w, h);
+}
+
+static GtkPrintOperationResult
+gtk_print_operation_unix_run_dialog (GtkPrintOperation *op,
+                                     gboolean           show_dialog,
+                                     GtkWindow         *parent,
+                                     gboolean          *do_print)
+ {
+  GtkWidget *pd;
+  PrintResponseData rdata;
+  const char *printer_name;
+
+  rdata.op = op;
+  rdata.do_print = FALSE;
+  rdata.do_preview = FALSE;
+  rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  rdata.print_cb = NULL;
+  rdata.destroy = NULL;
+  rdata.parent = parent;
+  rdata.loop = NULL;
+
+  if (show_dialog)
+    {
+      pd = get_print_dialog (op, parent);
+      gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
+
+      g_signal_connect (pd, "response",
+                       G_CALLBACK (handle_print_response), &rdata);
+
+      gtk_window_present (GTK_WINDOW (pd));
+
+      rdata.loop = g_main_loop_new (NULL, FALSE);
+      g_main_loop_run (rdata.loop);
+      g_main_loop_unref (rdata.loop);
+      rdata.loop = NULL;
+    }
+  else
+    {
+      printer_name = NULL;
+      if (op->priv->print_settings)
+       printer_name = gtk_print_settings_get_printer (op->priv->print_settings);
+
+      rdata.loop = g_main_loop_new (NULL, FALSE);
+      find_printer (printer_name,
+                   (GFunc) found_printer, &rdata);
+
+      g_main_loop_run (rdata.loop);
+      g_main_loop_unref (rdata.loop);
+      rdata.loop = NULL;
+    }
+
+  *do_print = rdata.do_print;
+
+  return rdata.result;
+}
+
+
+typedef struct
+{
+  GtkPageSetup         *page_setup;
+  GtkPageSetupDoneFunc  done_cb;
+  gpointer              data;
+  GDestroyNotify        destroy;
+  GMainLoop            *loop;
+} PageSetupResponseData;
+
+static void
+page_setup_data_free (gpointer data)
+{
+  PageSetupResponseData *rdata = data;
+
+  if (rdata->page_setup)
+    g_object_unref (rdata->page_setup);
+
+  g_free (rdata);
+}
+
+static void
+handle_page_setup_response (GtkWidget *dialog,
+                           int        response,
+                           gpointer   data)
+{
+  GtkPageSetupUnixDialog *psd;
+  PageSetupResponseData *rdata = data;
+
+  if (rdata->loop)
+    g_main_loop_quit (rdata->loop);
+
+  psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
+  if (response == GTK_RESPONSE_OK)
+    rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
+
+  gtk_window_destroy (GTK_WINDOW (dialog));
+
+  if (rdata->done_cb)
+    rdata->done_cb (rdata->page_setup, rdata->data);
+
+  if (rdata->destroy)
+    rdata->destroy (rdata);
+}
+
+static GtkWidget *
+get_page_setup_dialog (GtkWindow        *parent,
+                      GtkPageSetup     *page_setup,
+                      GtkPrintSettings *settings)
+{
+  GtkWidget *dialog;
+
+  dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
+  if (page_setup)
+    gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
+                                              page_setup);
+  gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
+                                                settings);
+
+  return dialog;
+}
+
+/**
+ * gtk_print_run_page_setup_dialog:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ *
+ * Runs a page setup dialog, letting the user modify the values from
+ * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
+ * is identical to the passed in @page_setup, otherwise it contains the
+ * modifications done in the dialog.
+ *
+ * Note that this function may use a recursive mainloop to show the page
+ * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
+ * a problem.
+ *
+ * Returns: (transfer full): a new `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_print_run_page_setup_dialog (GtkWindow        *parent,
+                                GtkPageSetup     *page_setup,
+                                GtkPrintSettings *settings)
+{
+  GtkWidget *dialog;
+  PageSetupResponseData rdata;
+
+  rdata.page_setup = NULL;
+  rdata.done_cb = NULL;
+  rdata.data = NULL;
+  rdata.destroy = NULL;
+  rdata.loop = g_main_loop_new (NULL, FALSE);
+
+  dialog = get_page_setup_dialog (parent, page_setup, settings);
+
+  g_signal_connect (dialog, "response",
+                    G_CALLBACK (handle_page_setup_response),
+                    &rdata);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+
+  g_main_loop_run (rdata.loop);
+  g_main_loop_unref (rdata.loop);
+  rdata.loop = NULL;
+
+  if (rdata.page_setup)
+    return rdata.page_setup;
+  else if (page_setup)
+    return gtk_page_setup_copy (page_setup);
+  else
+    return gtk_page_setup_new ();
+}
+
+/**
+ * gtk_print_run_page_setup_dialog_async:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ * @done_cb: (scope async): a function to call when the user saves
+ *    the modified page setup
+ * @data: user data to pass to @done_cb
+ *
+ * Runs a page setup dialog, letting the user modify the values from @page_setup.
+ *
+ * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after
+ * showing the page setup dialog on platforms that support this, and calls @done_cb
+ * from a signal handler for the ::response signal of the dialog.
+ */
+void
+gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
+                                      GtkPageSetup         *page_setup,
+                                      GtkPrintSettings     *settings,
+                                      GtkPageSetupDoneFunc  done_cb,
+                                      gpointer              data)
+{
+  GtkWidget *dialog;
+  PageSetupResponseData *rdata;
+
+  dialog = get_page_setup_dialog (parent, page_setup, settings);
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+  rdata = g_new (PageSetupResponseData, 1);
+  rdata->page_setup = NULL;
+  rdata->done_cb = done_cb;
+  rdata->data = data;
+  rdata->destroy = page_setup_data_free;
+  rdata->loop = NULL;
+
+  g_signal_connect (dialog, "response",
+                   G_CALLBACK (handle_page_setup_response), rdata);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+struct _PrinterFinder
+{
+  gboolean found_printer;
+  GFunc func;
+  gpointer data;
+  char *printer_name;
+  GList *backends;
+  guint timeout_tag;
+  GtkPrinter *printer;
+  GtkPrinter *default_printer;
+  GtkPrinter *first_printer;
+};
+
+static gboolean
+find_printer_idle (gpointer data)
+{
+  PrinterFinder *finder = data;
+  GtkPrinter *printer;
+
+  if (finder->printer != NULL)
+    printer = finder->printer;
+  else if (finder->default_printer != NULL)
+    printer = finder->default_printer;
+  else if (finder->first_printer != NULL)
+    printer = finder->first_printer;
+  else
+    printer = NULL;
+
+  finder->func (printer, finder->data);
+
+  printer_finder_free (finder);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+printer_added_cb (GtkPrintBackend *backend,
+                  GtkPrinter      *printer,
+                 PrinterFinder   *finder)
+{
+  if (finder->found_printer)
+    return;
+
+  /* FIXME this skips "Print to PDF" - is this intentional ? */
+  if (gtk_printer_is_virtual (printer))
+    return;
+
+  if (finder->printer_name != NULL &&
+      strcmp (gtk_printer_get_name (printer), finder->printer_name) == 0)
+    {
+      finder->printer = g_object_ref (printer);
+      finder->found_printer = TRUE;
+    }
+  else if (finder->default_printer == NULL &&
+          gtk_printer_is_default (printer))
+    {
+      finder->default_printer = g_object_ref (printer);
+      if (finder->printer_name == NULL)
+       finder->found_printer = TRUE;
+    }
+  else
+    {
+      if (finder->first_printer == NULL)
+        finder->first_printer = g_object_ref (printer);
+    }
+
+  if (finder->found_printer)
+    g_idle_add (find_printer_idle, finder);
+}
+
+static void
+printer_list_done_cb (GtkPrintBackend *backend,
+                     PrinterFinder   *finder)
+{
+  finder->backends = g_list_remove (finder->backends, backend);
+
+  g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+  g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+
+  gtk_print_backend_destroy (backend);
+  g_object_unref (backend);
+
+  if (finder->backends == NULL)
+    g_idle_add (find_printer_idle, finder);
+}
+
+static void
+find_printer_init (PrinterFinder   *finder,
+                  GtkPrintBackend *backend)
+{
+  GList *list;
+  GList *node;
+
+  list = gtk_print_backend_get_printer_list (backend);
+
+  node = list;
+  while (node != NULL)
+    {
+      printer_added_cb (backend, node->data, finder);
+      node = node->next;
+
+      if (finder->found_printer)
+       break;
+    }
+
+  g_list_free (list);
+
+  if (gtk_print_backend_printer_list_is_done (backend))
+    {
+      finder->backends = g_list_remove (finder->backends, backend);
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+  else
+    {
+      g_signal_connect (backend, "printer-added",
+                       (GCallback) printer_added_cb,
+                       finder);
+      g_signal_connect (backend, "printer-list-done",
+                       (GCallback) printer_list_done_cb,
+                       finder);
+    }
+
+}
+
+static void
+printer_finder_free (PrinterFinder *finder)
+{
+  GList *l;
+
+  g_free (finder->printer_name);
+
+  if (finder->printer)
+    g_object_unref (finder->printer);
+
+  if (finder->default_printer)
+    g_object_unref (finder->default_printer);
+
+  if (finder->first_printer)
+    g_object_unref (finder->first_printer);
+
+  for (l = finder->backends; l != NULL; l = l->next)
+    {
+      GtkPrintBackend *backend = l->data;
+      g_signal_handlers_disconnect_by_func (backend, printer_added_cb, finder);
+      g_signal_handlers_disconnect_by_func (backend, printer_list_done_cb, finder);
+      gtk_print_backend_destroy (backend);
+      g_object_unref (backend);
+    }
+
+  g_list_free (finder->backends);
+
+  g_free (finder);
+}
+
+static void
+find_printer (const char *printer,
+             GFunc        func,
+             gpointer     data)
+{
+  GList *node, *next;
+  PrinterFinder *finder;
+
+  finder = g_new0 (PrinterFinder, 1);
+
+  finder->printer_name = g_strdup (printer);
+  finder->func = func;
+  finder->data = data;
+
+  finder->backends = NULL;
+  if (g_module_supported ())
+    finder->backends = gtk_print_backend_load_modules ();
+
+  for (node = finder->backends; !finder->found_printer && node != NULL; node = next)
+    {
+      next = node->next;
+      find_printer_init (finder, GTK_PRINT_BACKEND (node->data));
+    }
+
+  if (finder->backends == NULL)
+    g_idle_add (find_printer_idle, finder);
+}
+
+
+GtkPrintOperationResult
+_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+                                                 gboolean           show_dialog,
+                                                 GtkWindow         *parent,
+                                                 gboolean          *do_print)
+{
+  if (gdk_should_use_portal ())
+    return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
+  else
+    return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
+}
+void
+_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
+                                                       gboolean                    show_dialog,
+                                                        GtkWindow                  *parent,
+                                                       GtkPrintOperationPrintFunc  print_cb)
+{
+  if (gdk_should_use_portal ())
+    gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
+  else
+    gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
+}
+
+void
+_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+                                                      cairo_surface_t   *surface,
+                                                      GtkWindow         *parent,
+                                                      const char        *filename)
+{
+  if (gdk_should_use_portal ())
+    gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
+  else
+    gtk_print_operation_unix_launch_preview (op, surface, parent, filename);
+}
+
+cairo_surface_t *
+_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             double            *dpi_x,
+                                                             double            *dpi_y,
+                                                             char             **target)
+{
+  return gtk_print_operation_unix_create_preview_surface (op, page_setup, dpi_x, dpi_y, target);
+}
+
+void
+_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             cairo_surface_t   *surface)
+{
+  gtk_print_operation_unix_resize_preview_surface (op, page_setup, surface);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+                                                         cairo_surface_t   *surface,
+                                                         cairo_t           *cr)
+{
+  gtk_print_operation_unix_preview_start_page (op, surface, cr);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+                                                       cairo_surface_t   *surface,
+                                                       cairo_t           *cr)
+{
+  gtk_print_operation_unix_preview_end_page (op, surface, cr);
+}
diff --git a/gtk/print/gtkprintoperation-win32.c b/gtk/print/gtkprintoperation-win32.c
new file mode 100644 (file)
index 0000000..15d68ab
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MSC_VER
+#ifndef _WIN32_WINNT
+/* Vista or newer */
+#define _WIN32_WINNT 0x0600
+#endif
+#ifndef WINVER
+#define WINVER _WIN32_WINNT
+#endif
+#endif
+
+#define COBJMACROS
+#include "config.h"
+#include <math.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <cairo-win32.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include "gtkprintoperation-private.h"
+#include "gtkprint-win32.h"
+#include "gtkwindow.h"
+#include "gtkprivate.h"
+#include "gtkwidgetprivate.h"
+#include "gtknative.h"
+#include "win32/gdkprivate-win32.h"
+
+#define MAX_PAGE_RANGES 20
+#define STATUS_POLLING_TIME 2000
+
+#ifndef JOB_STATUS_RESTART
+#define JOB_STATUS_RESTART 0x800
+#endif
+
+#ifndef JOB_STATUS_COMPLETE
+#define JOB_STATUS_COMPLETE 0x1000
+#endif
+
+/* Forward declarations */
+GtkPrintOperationResult
+gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
+                                       gboolean          *do_print);
+GtkPrintOperationResult
+gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
+                                    GtkWindow         *parent,
+                                    gboolean          *do_print);
+UINT_PTR CALLBACK
+run_mainloop_hook (HWND hdlg,
+                  UINT uiMsg,
+                  WPARAM wParam,
+                  LPARAM lParam);
+void
+win32_start_page (GtkPrintOperation *op,
+                 GtkPrintContext *print_context,
+                 GtkPageSetup *page_setup);
+
+typedef struct {
+  HDC hdc;
+  HGLOBAL devmode;
+  HGLOBAL devnames;
+  HANDLE printerHandle;
+  int job_id;
+  guint timeout_id;
+
+  cairo_surface_t *surface;
+  GtkWidget *embed_widget;
+} GtkPrintOperationWin32;
+
+static void win32_poll_status (GtkPrintOperation *op);
+
+static const GUID myIID_IPrintDialogCallback  = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
+
+#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
+#undef INTERFACE
+#define INTERFACE IPrintDialogCallback
+DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
+{
+    STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
+    STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_ (ULONG, Release)(THIS) PURE;
+    STDMETHOD (InitDone)(THIS) PURE;
+    STDMETHOD (SelectionChange)(THIS) PURE;
+    STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
+}; 
+#endif
+
+static UINT got_gdk_events_message;
+
+UINT_PTR CALLBACK
+run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+  if (uiMsg == WM_INITDIALOG)
+    {
+      gdk_win32_set_modal_dialog_libgtk_only (hdlg);
+      while (g_main_context_pending (NULL))
+       g_main_context_iteration (NULL, TRUE);
+    }
+  else if (uiMsg == got_gdk_events_message)
+    {
+      while (g_main_context_pending (NULL))
+       g_main_context_iteration (NULL, TRUE);
+      return 1;
+    }
+  return 0;
+}
+
+static GtkPageOrientation
+orientation_from_win32 (short orientation)
+{
+  if (orientation == DMORIENT_LANDSCAPE)
+    return GTK_PAGE_ORIENTATION_LANDSCAPE;
+  return GTK_PAGE_ORIENTATION_PORTRAIT;
+}
+
+static short
+orientation_to_win32 (GtkPageOrientation orientation)
+{
+  if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
+      orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
+    return DMORIENT_LANDSCAPE;
+  return DMORIENT_PORTRAIT;
+}
+
+static GtkPaperSize *
+paper_size_from_win32 (short size)
+{
+  const char *name;
+  
+  switch (size)
+    {
+    case DMPAPER_LETTER_TRANSVERSE:
+    case DMPAPER_LETTER:
+    case DMPAPER_LETTERSMALL:
+      name = "na_letter";
+      break;
+    case DMPAPER_TABLOID:
+    case DMPAPER_LEDGER:
+      name = "na_ledger";
+      break;
+    case DMPAPER_LEGAL:
+      name = "na_legal";
+      break;
+    case DMPAPER_STATEMENT:
+      name = "na_invoice";
+      break;
+    case DMPAPER_EXECUTIVE:
+      name = "na_executive";
+      break;
+    case DMPAPER_A3:
+    case DMPAPER_A3_TRANSVERSE:
+      name = "iso_a3";
+      break;
+    case DMPAPER_A4:
+    case DMPAPER_A4SMALL:
+    case DMPAPER_A4_TRANSVERSE:
+      name = "iso_a4";
+      break;
+    case DMPAPER_A5:
+    case DMPAPER_A5_TRANSVERSE:
+      name = "iso_a5";
+      break;
+    case DMPAPER_B4:
+      name = "jis_b4";
+      break;
+    case DMPAPER_B5:
+    case DMPAPER_B5_TRANSVERSE:
+      name = "jis_b5";
+      break;
+    case DMPAPER_QUARTO:
+      name = "na_quarto";
+      break;
+    case DMPAPER_10X14:
+      name = "na_10x14";
+      break;
+    case DMPAPER_11X17:
+      name = "na_ledger";
+      break;
+    case DMPAPER_NOTE:
+      name = "na_letter";
+      break;
+    case DMPAPER_ENV_9:
+      name = "na_number-9";
+      break;
+    case DMPAPER_ENV_10:
+      name = "na_number-10";
+      break;
+    case DMPAPER_ENV_11:
+      name = "na_number-11";
+      break;
+    case DMPAPER_ENV_12:
+      name = "na_number-12";
+      break;
+    case DMPAPER_ENV_14:
+      name = "na_number-14";
+      break;
+    case DMPAPER_CSHEET:
+      name = "na_c";
+      break;
+    case DMPAPER_DSHEET:
+      name = "na_d";
+      break;
+    case DMPAPER_ESHEET:
+      name = "na_e";
+      break;
+    case DMPAPER_ENV_DL:
+      name = "iso_dl";
+      break;
+    case DMPAPER_ENV_C5:
+      name = "iso_c5";
+      break;
+    case DMPAPER_ENV_C3:
+      name = "iso_c3";
+      break;
+    case DMPAPER_ENV_C4:
+      name = "iso_c4";
+      break;
+    case DMPAPER_ENV_C6:
+      name = "iso_c6";
+      break;
+    case DMPAPER_ENV_C65:
+      name = "iso_c6c5";
+      break;
+    case DMPAPER_ENV_B4:
+      name = "iso_b4";
+      break;
+    case DMPAPER_ENV_B5:
+      name = "iso_b5";
+      break;
+    case DMPAPER_ENV_B6:
+      name = "iso_b6";
+      break;
+    case DMPAPER_ENV_ITALY:
+      name = "om_italian";
+      break;
+    case DMPAPER_ENV_MONARCH:
+      name = "na_monarch";
+      break;
+    case DMPAPER_ENV_PERSONAL:
+      name = "na_personal";
+      break;
+    case DMPAPER_FANFOLD_US:
+      name = "na_fanfold-us";
+      break;
+    case DMPAPER_FANFOLD_STD_GERMAN:
+      name = "na_fanfold-eur";
+      break;
+    case DMPAPER_FANFOLD_LGL_GERMAN:
+      name = "na_foolscap";
+      break;
+    case DMPAPER_ISO_B4:
+      name = "iso_b4";
+      break;
+    case DMPAPER_JAPANESE_POSTCARD:
+      name = "jpn_hagaki";
+      break;
+    case DMPAPER_9X11:
+      name = "na_9x11";
+      break;
+    case DMPAPER_10X11:
+      name = "na_10x11";
+      break;
+    case DMPAPER_ENV_INVITE:
+      name = "om_invite";
+       break;
+    case DMPAPER_LETTER_EXTRA:
+    case DMPAPER_LETTER_EXTRA_TRANSVERSE:
+      name = "na_letter-extra";
+      break;
+    case DMPAPER_LEGAL_EXTRA:
+      name = "na_legal-extra";
+      break;
+    case DMPAPER_TABLOID_EXTRA:
+      name = "na_arch";
+      break;
+    case DMPAPER_A4_EXTRA:
+      name = "iso_a4-extra";
+      break;
+    case DMPAPER_B_PLUS:
+      name = "na_b-plus";
+      break;
+    case DMPAPER_LETTER_PLUS:
+      name = "na_letter-plus";
+      break;
+    case DMPAPER_A3_EXTRA:
+    case DMPAPER_A3_EXTRA_TRANSVERSE:
+      name = "iso_a3-extra";
+      break;
+    case DMPAPER_A5_EXTRA:
+      name = "iso_a5-extra";
+      break;
+    case DMPAPER_B5_EXTRA:
+      name = "iso_b5-extra";
+      break;
+    case DMPAPER_A2:
+      name = "iso_a2";
+      break;
+      
+    default:
+      name = NULL;
+      break;
+    }
+
+  if (name)
+    return gtk_paper_size_new (name);
+  else 
+    return NULL;
+}
+
+static short
+paper_size_to_win32 (GtkPaperSize *paper_size)
+{
+  const char *format;
+
+  if (gtk_paper_size_is_custom (paper_size))
+    return 0;
+  
+  format = gtk_paper_size_get_name (paper_size);
+
+  if (strcmp (format, "na_letter") == 0)
+    return DMPAPER_LETTER;
+  if (strcmp (format, "na_ledger") == 0)
+    return DMPAPER_LEDGER;
+  if (strcmp (format, "na_legal") == 0)
+    return DMPAPER_LEGAL;
+  if (strcmp (format, "na_invoice") == 0)
+    return DMPAPER_STATEMENT;
+  if (strcmp (format, "na_executive") == 0)
+    return DMPAPER_EXECUTIVE;
+  if (strcmp (format, "iso_a2") == 0)
+    return DMPAPER_A2;
+  if (strcmp (format, "iso_a3") == 0)
+    return DMPAPER_A3;
+  if (strcmp (format, "iso_a4") == 0)
+    return DMPAPER_A4;
+  if (strcmp (format, "iso_a5") == 0)
+    return DMPAPER_A5;
+  if (strcmp (format, "iso_b4") == 0)
+    return DMPAPER_B4;
+  if (strcmp (format, "iso_b5") == 0)
+    return DMPAPER_B5;
+  if (strcmp (format, "na_quarto") == 0)
+    return DMPAPER_QUARTO;
+  if (strcmp (format, "na_10x14") == 0)
+    return DMPAPER_10X14;
+  if (strcmp (format, "na_number-9") == 0)
+    return DMPAPER_ENV_9;
+  if (strcmp (format, "na_number-10") == 0)
+    return DMPAPER_ENV_10;
+  if (strcmp (format, "na_number-11") == 0)
+    return DMPAPER_ENV_11;
+  if (strcmp (format, "na_number-12") == 0)
+    return DMPAPER_ENV_12;
+  if (strcmp (format, "na_number-14") == 0)
+    return DMPAPER_ENV_14;
+  if (strcmp (format, "na_c") == 0)
+    return DMPAPER_CSHEET;
+  if (strcmp (format, "na_d") == 0)
+    return DMPAPER_DSHEET;
+  if (strcmp (format, "na_e") == 0)
+    return DMPAPER_ESHEET;
+  if (strcmp (format, "iso_dl") == 0)
+    return DMPAPER_ENV_DL;
+  if (strcmp (format, "iso_c3") == 0)
+    return DMPAPER_ENV_C3;
+  if (strcmp (format, "iso_c4") == 0)
+    return DMPAPER_ENV_C4;
+  if (strcmp (format, "iso_c5") == 0)
+    return DMPAPER_ENV_C5;
+  if (strcmp (format, "iso_c6") == 0)
+    return DMPAPER_ENV_C6;
+  if (strcmp (format, "iso_c5c6") == 0)
+    return DMPAPER_ENV_C65;
+  if (strcmp (format, "iso_b6") == 0)
+    return DMPAPER_ENV_B6;
+  if (strcmp (format, "om_italian") == 0)
+    return DMPAPER_ENV_ITALY;
+  if (strcmp (format, "na_monarch") == 0)
+    return DMPAPER_ENV_MONARCH;
+  if (strcmp (format, "na_personal") == 0)
+    return DMPAPER_ENV_PERSONAL;
+  if (strcmp (format, "na_fanfold-us") == 0)
+    return DMPAPER_FANFOLD_US;
+  if (strcmp (format, "na_fanfold-eur") == 0)
+    return DMPAPER_FANFOLD_STD_GERMAN;
+  if (strcmp (format, "na_foolscap") == 0)
+    return DMPAPER_FANFOLD_LGL_GERMAN;
+  if (strcmp (format, "jpn_hagaki") == 0)
+    return DMPAPER_JAPANESE_POSTCARD;
+  if (strcmp (format, "na_9x11") == 0)
+    return DMPAPER_9X11;
+  if (strcmp (format, "na_10x11") == 0)
+    return DMPAPER_10X11;
+  if (strcmp (format, "om_invite") == 0)
+    return DMPAPER_ENV_INVITE;
+  if (strcmp (format, "na_letter-extra") == 0)
+    return DMPAPER_LETTER_EXTRA;
+  if (strcmp (format, "na_legal-extra") == 0)
+    return DMPAPER_LEGAL_EXTRA;
+  if (strcmp (format, "na_arch") == 0)
+    return DMPAPER_TABLOID_EXTRA;
+  if (strcmp (format, "iso_a3-extra") == 0)
+    return DMPAPER_A3_EXTRA;
+  if (strcmp (format, "iso_a4-extra") == 0)
+    return DMPAPER_A4_EXTRA;
+  if (strcmp (format, "iso_a5-extra") == 0)
+    return DMPAPER_A5_EXTRA;
+  if (strcmp (format, "iso_b5-extra") == 0)
+    return DMPAPER_B5_EXTRA;
+  if (strcmp (format, "na_b-plus") == 0)
+    return DMPAPER_B_PLUS;
+  if (strcmp (format, "na_letter-plus") == 0)
+    return DMPAPER_LETTER_PLUS;
+
+  return 0;
+}
+
+static char *
+get_default_printer (void)
+{
+  wchar_t *win32_printer_name = NULL;
+  char *printer_name = NULL;
+  DWORD needed;
+
+  GetDefaultPrinterW (NULL, &needed);
+  win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
+  if (!GetDefaultPrinterW (win32_printer_name, &needed))
+    {
+      g_free (win32_printer_name);
+      return NULL;
+    }
+  printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
+  g_free (win32_printer_name);
+
+  return printer_name;
+}
+
+static void
+set_hard_margins (GtkPrintOperation *op)
+{
+  double top, bottom, left, right;
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+  top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+  bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
+      - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
+  left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+  right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
+      - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
+
+  _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
+}
+
+void
+win32_start_page (GtkPrintOperation *op,
+                 GtkPrintContext *print_context,
+                 GtkPageSetup *page_setup)
+{
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+  LPDEVMODEW devmode;
+  GtkPaperSize *paper_size;
+  double x_off, y_off;
+
+  devmode = GlobalLock (op_win32->devmode);
+  
+  devmode->dmFields |= DM_ORIENTATION;
+  devmode->dmOrientation =
+    orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
+  
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+  devmode->dmFields |= DM_PAPERSIZE;
+  devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
+  devmode->dmPaperSize = paper_size_to_win32 (paper_size);
+  if (devmode->dmPaperSize == 0)
+    {
+      devmode->dmPaperSize = DMPAPER_USER;
+      devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
+
+      /* Lengths in DEVMODE are in tenths of a millimeter */
+      devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
+      devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
+    }
+  
+  ResetDCW (op_win32->hdc, devmode);
+  
+  GlobalUnlock (op_win32->devmode);
+
+  set_hard_margins (op);
+  x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+  y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+  cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
+  
+  StartPage (op_win32->hdc);
+}
+
+static void
+win32_end_page (GtkPrintOperation *op,
+               GtkPrintContext *print_context)
+{
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+  cairo_surface_show_page (op_win32->surface);
+
+  EndPage (op_win32->hdc);
+}
+
+static gboolean
+win32_poll_status_timeout (GtkPrintOperation *op)
+{
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+  
+  op_win32->timeout_id = 0;
+  /* We need to ref this, as setting the status to finished
+     might unref the object */
+  g_object_ref (op);
+  win32_poll_status (op);
+
+  if (!gtk_print_operation_is_finished (op)) {
+    op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
+                                         (GSourceFunc)win32_poll_status_timeout,
+                                         op);
+    gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
+  }
+  g_object_unref (op);
+  return FALSE;
+}
+
+
+static void
+win32_end_run (GtkPrintOperation *op,
+              gboolean           wait,
+              gboolean           cancelled)
+{
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+  LPDEVNAMES devnames;
+  HANDLE printerHandle = 0;
+
+  cairo_surface_finish (op_win32->surface);
+  
+  EndDoc (op_win32->hdc);
+
+  if (op->priv->track_print_status)
+    {
+      devnames = GlobalLock (op_win32->devnames);
+      if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
+                        &printerHandle, NULL))
+       printerHandle = 0;
+      GlobalUnlock (op_win32->devnames);
+    }
+  
+  GlobalFree (op_win32->devmode);
+  GlobalFree (op_win32->devnames);
+
+  cairo_surface_destroy (op_win32->surface);
+  op_win32->surface = NULL;
+
+  DeleteDC (op_win32->hdc);
+  
+  if (printerHandle != 0)
+    {
+      op_win32->printerHandle = printerHandle;
+      win32_poll_status (op);
+      op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME,
+                                           (GSourceFunc)win32_poll_status_timeout,
+                                           op);
+      gdk_source_set_static_name_by_id (op_win32->timeout_id, "[gtk] win32_poll_status_timeout");
+    }
+  else
+    /* Dunno what happened, pretend its finished */
+    _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
+}
+
+static void
+win32_poll_status (GtkPrintOperation *op)
+{
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+  guchar *data;
+  DWORD needed;
+  JOB_INFO_1W *job_info;
+  GtkPrintStatus status;
+  char *status_str;
+  BOOL ret;
+
+  GetJobW (op_win32->printerHandle, op_win32->job_id,
+          1,(LPBYTE)NULL, 0, &needed);
+  data = g_malloc (needed);
+  ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
+                1, (LPBYTE)data, needed, &needed);
+
+  status_str = NULL;
+  if (ret)
+    {
+      DWORD win32_status;
+      job_info = (JOB_INFO_1W *)data;
+      win32_status = job_info->Status;
+
+      if (job_info->pStatus)
+       status_str = g_utf16_to_utf8 (job_info->pStatus, 
+                                     -1, NULL, NULL, NULL);
+     
+      if (win32_status &
+         (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
+       status = GTK_PRINT_STATUS_FINISHED;
+      else if (win32_status &
+              (JOB_STATUS_OFFLINE |
+               JOB_STATUS_PAPEROUT |
+               JOB_STATUS_PAUSED |
+               JOB_STATUS_USER_INTERVENTION))
+       {
+         status = GTK_PRINT_STATUS_PENDING_ISSUE;
+         if (status_str == NULL)
+           {
+             if (win32_status & JOB_STATUS_OFFLINE)
+               status_str = g_strdup (_("Printer offline"));
+             else if (win32_status & JOB_STATUS_PAPEROUT)
+               status_str = g_strdup (_("Out of paper"));
+             else if (win32_status & JOB_STATUS_PAUSED)
+               status_str = g_strdup (_("Paused"));
+             else if (win32_status & JOB_STATUS_USER_INTERVENTION)
+               status_str = g_strdup (_("Need user intervention"));
+           }
+       }
+      else if (win32_status &
+              (JOB_STATUS_BLOCKED_DEVQ |
+               JOB_STATUS_DELETED |
+               JOB_STATUS_ERROR))
+       status = GTK_PRINT_STATUS_FINISHED_ABORTED;
+      else if (win32_status &
+              (JOB_STATUS_SPOOLING |
+               JOB_STATUS_DELETING))
+       status = GTK_PRINT_STATUS_PENDING;
+      else if (win32_status & JOB_STATUS_PRINTING)
+       status = GTK_PRINT_STATUS_PRINTING;
+      else
+       status = GTK_PRINT_STATUS_FINISHED;
+    }
+  else
+    status = GTK_PRINT_STATUS_FINISHED;
+
+  g_free (data);
+
+  _gtk_print_operation_set_status (op, status, status_str);
+  g_free (status_str);
+}
+
+static void
+op_win32_free (GtkPrintOperationWin32 *op_win32)
+{
+  if (op_win32->printerHandle)
+    ClosePrinter (op_win32->printerHandle);
+  if (op_win32->timeout_id != 0)
+    g_source_remove (op_win32->timeout_id);
+  g_free (op_win32);
+}
+
+static HWND
+get_parent_hwnd (GtkWidget *widget)
+{
+  GtkNative *native;
+
+  native = gtk_widget_get_native (widget);
+  gtk_widget_realize (GTK_WIDGET (native));
+  return gdk_win32_surface_get_handle (gtk_native_get_surface (native));
+}
+
+static void
+devnames_to_settings (GtkPrintSettings *settings,
+                     HANDLE hDevNames)
+{
+  GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
+  gtk_print_settings_set_printer (settings, devnames->device);
+  gtk_print_win32_devnames_free (devnames);
+}
+
+static void
+devmode_to_settings (GtkPrintSettings *settings,
+                    HANDLE hDevMode)
+{
+  LPDEVMODEW devmode;
+
+  devmode = GlobalLock (hDevMode);
+  
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
+                             devmode->dmDriverVersion);
+  if (devmode->dmDriverExtra != 0)
+    {
+      char *extra = g_base64_encode (((const guchar *)devmode) + sizeof (DEVMODEW),
+                                    devmode->dmDriverExtra);
+      gtk_print_settings_set (settings,
+                             GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
+                             extra);
+      g_free (extra);
+    }
+  
+  char *devmode_name = g_utf16_to_utf8 (devmode->dmDeviceName, -1, NULL, NULL, NULL);
+  gtk_print_settings_set (settings, "win32-devmode-name", devmode_name);
+  g_free (devmode_name);
+
+  if (devmode->dmFields & DM_ORIENTATION)
+    gtk_print_settings_set_orientation (settings,
+                                       orientation_from_win32 (devmode->dmOrientation));
+  
+  
+  if (devmode->dmFields & DM_PAPERSIZE &&
+      devmode->dmPaperSize != 0)
+    {
+      GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
+      if (paper_size)
+       {
+         gtk_print_settings_set_paper_size (settings, paper_size);
+         gtk_paper_size_free (paper_size);
+       }
+      gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
+    }
+  else if ((devmode->dmFields & DM_PAPERSIZE &&
+           devmode->dmPaperSize == 0) ||
+          ((devmode->dmFields & DM_PAPERWIDTH) &&
+           (devmode->dmFields & DM_PAPERLENGTH)))
+    {
+      GtkPaperSize *paper_size;
+      char *form_name = NULL;
+      if (devmode->dmFields & DM_FORMNAME)
+       form_name = g_utf16_to_utf8 (devmode->dmFormName, 
+                                    -1, NULL, NULL, NULL);
+      if (form_name == NULL || form_name[0] == 0)
+       form_name = g_strdup (_("Custom size"));
+
+      /* Lengths in DEVMODE are in tenths of a millimeter */
+      paper_size = gtk_paper_size_new_custom (form_name,
+                                             form_name,
+                                             devmode->dmPaperWidth / 10.0,
+                                             devmode->dmPaperLength / 10.0,
+                                             GTK_UNIT_MM);
+      gtk_print_settings_set_paper_size (settings, paper_size);
+      gtk_paper_size_free (paper_size);
+    }
+  
+  if (devmode->dmFields & DM_SCALE)
+    gtk_print_settings_set_scale (settings, devmode->dmScale);
+  
+  if (devmode->dmFields & DM_COPIES)
+    gtk_print_settings_set_n_copies (settings,
+                                    devmode->dmCopies);
+  
+  if (devmode->dmFields & DM_DEFAULTSOURCE)
+    {
+      const char *source;
+      switch (devmode->dmDefaultSource)
+       {
+       default:
+       case DMBIN_AUTO:
+         source = "auto";
+         break;
+       case DMBIN_CASSETTE:
+         source = "cassette";
+         break;
+       case DMBIN_ENVELOPE:
+         source = "envelope";
+         break;
+       case DMBIN_ENVMANUAL:
+         source = "envelope-manual";
+         break;
+       case DMBIN_LOWER:
+         source = "lower";
+         break;
+       case DMBIN_MANUAL:
+         source = "manual";
+         break;
+       case DMBIN_MIDDLE:
+         source = "middle";
+         break;
+       case DMBIN_ONLYONE:
+         source = "only-one";
+         break;
+       case DMBIN_FORMSOURCE:
+         source = "form-source";
+         break;
+       case DMBIN_LARGECAPACITY:
+         source = "large-capacity";
+         break;
+       case DMBIN_LARGEFMT:
+         source = "large-format";
+         break;
+       case DMBIN_TRACTOR:
+         source = "tractor";
+         break;
+       case DMBIN_SMALLFMT:
+         source = "small-format";
+         break;
+       }
+      gtk_print_settings_set_default_source (settings, source);
+      gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
+    }
+  
+  if (devmode->dmFields & DM_PRINTQUALITY)
+    {
+      GtkPrintQuality quality;
+      switch (devmode->dmPrintQuality)
+       {
+       case DMRES_LOW:
+         quality = GTK_PRINT_QUALITY_LOW;
+         break;
+       case DMRES_MEDIUM:
+         quality = GTK_PRINT_QUALITY_NORMAL;
+         break;
+       default:
+       case DMRES_HIGH:
+         quality = GTK_PRINT_QUALITY_HIGH;
+         break;
+       case DMRES_DRAFT:
+         quality = GTK_PRINT_QUALITY_DRAFT;
+         break;
+       }
+      gtk_print_settings_set_quality (settings, quality);
+      gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
+    }
+  
+  if (devmode->dmFields & DM_COLOR)
+    gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
+  
+  if (devmode->dmFields & DM_DUPLEX)
+    {
+      GtkPrintDuplex duplex;
+      switch (devmode->dmDuplex)
+       {
+       default:
+       case DMDUP_SIMPLEX:
+         duplex = GTK_PRINT_DUPLEX_SIMPLEX;
+         break;
+       case DMDUP_HORIZONTAL:
+         duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
+         break;
+       case DMDUP_VERTICAL:
+         duplex = GTK_PRINT_DUPLEX_VERTICAL;
+         break;
+       }
+      
+      gtk_print_settings_set_duplex (settings, duplex);
+    }
+  
+  if (devmode->dmFields & DM_COLLATE)
+    gtk_print_settings_set_collate (settings,
+                                   devmode->dmCollate == DMCOLLATE_TRUE);
+  
+  if (devmode->dmFields & DM_MEDIATYPE)
+    {
+      const char *media_type;
+      switch (devmode->dmMediaType)
+       {
+       default:
+       case DMMEDIA_STANDARD:
+         media_type = "stationery";
+         break;
+       case DMMEDIA_TRANSPARENCY:
+         media_type = "transparency";
+         break;
+       case DMMEDIA_GLOSSY:
+         media_type = "photographic-glossy";
+         break;
+       }
+      gtk_print_settings_set_media_type (settings, media_type);
+      gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
+    }
+  
+  if (devmode->dmFields & DM_DITHERTYPE)
+    {
+      const char *dither;
+      switch (devmode->dmDitherType)
+       {
+       default:
+       case DMDITHER_FINE:
+         dither = "fine";
+         break;
+       case DMDITHER_NONE:
+         dither = "none";
+         break;
+       case DMDITHER_COARSE:
+         dither = "coarse";
+         break;
+       case DMDITHER_LINEART:
+         dither = "lineart";
+         break;
+       case DMDITHER_GRAYSCALE:
+         dither = "grayscale";
+         break;
+       case DMDITHER_ERRORDIFFUSION:
+         dither = "error-diffusion";
+         break;
+       }
+      gtk_print_settings_set_dither (settings, dither);
+      gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
+    }
+  
+  GlobalUnlock (hDevMode);
+}
+
+static void
+dialog_to_print_settings (GtkPrintOperation *op,
+                         LPPRINTDLGEXW printdlgex)
+{
+  guint i;
+  GtkPrintSettings *settings;
+
+  settings = gtk_print_settings_new ();
+
+  gtk_print_settings_set_print_pages (settings,
+                                     GTK_PRINT_PAGES_ALL);
+  if (printdlgex->Flags & PD_CURRENTPAGE)
+    gtk_print_settings_set_print_pages (settings,
+                                       GTK_PRINT_PAGES_CURRENT);
+  else if (printdlgex->Flags & PD_PAGENUMS)
+    gtk_print_settings_set_print_pages (settings,
+                                       GTK_PRINT_PAGES_RANGES);
+
+  if (printdlgex->nPageRanges > 0)
+    {
+      GtkPageRange *ranges;
+      ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
+
+      for (i = 0; i < printdlgex->nPageRanges; i++)
+       {
+         ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
+         ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
+       }
+
+      gtk_print_settings_set_page_ranges (settings, ranges,
+                                         printdlgex->nPageRanges);
+      g_free (ranges);
+    }
+  
+  if (printdlgex->hDevNames != NULL)
+    devnames_to_settings (settings, printdlgex->hDevNames);
+
+  if (printdlgex->hDevMode != NULL)
+    devmode_to_settings (settings, printdlgex->hDevMode);
+  
+  gtk_print_operation_set_print_settings (op, settings);
+}
+
+static HANDLE
+devmode_from_settings (GtkPrintSettings *settings,
+                      GtkPageSetup *page_setup,
+                      HANDLE hDevModeParam)
+{
+  HANDLE hDevMode = hDevModeParam;
+  LPDEVMODEW devmode;
+  guchar *extras;
+  GtkPaperSize *paper_size;
+  const char *extras_base64;
+  gsize extras_len;
+  const char *val;
+
+  /* If we already provided a valid hDevMode, don't initialize a new one; just lock the one we have */
+  if (hDevMode)
+    {
+      devmode = GlobalLock (hDevMode);
+    }
+  else
+    {
+      extras = NULL;
+      extras_len = 0;
+      extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
+      if (extras_base64)
+        extras = g_base64_decode (extras_base64, &extras_len);
+  
+      hDevMode = GlobalAlloc (GMEM_MOVEABLE, 
+                             sizeof (DEVMODEW) + extras_len);
+
+      devmode = GlobalLock (hDevMode);
+
+      memset (devmode, 0, sizeof (DEVMODEW));
+  
+      devmode->dmSpecVersion = DM_SPECVERSION;
+      devmode->dmSize = sizeof (DEVMODEW);
+  
+      gunichar2 *device_name = g_utf8_to_utf16 (gtk_print_settings_get (settings, "win32-devmode-name"), -1, NULL, NULL, NULL);
+      memcpy (devmode->dmDeviceName, device_name, CCHDEVICENAME);
+      g_free (device_name);
+
+
+      devmode->dmDriverExtra = 0;
+      if (extras && extras_len > 0)
+        {
+          devmode->dmDriverExtra = extras_len;
+          memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
+        }
+      g_free (extras);
+  
+      if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
+        {
+          devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
+        }
+    }
+  
+  if (page_setup ||
+      gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+    {
+      GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
+      if (page_setup)
+       orientation = gtk_page_setup_get_orientation (page_setup);
+      devmode->dmFields |= DM_ORIENTATION;
+      devmode->dmOrientation = orientation_to_win32 (orientation);
+    }
+
+  if (page_setup)
+    paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
+  else
+    {
+      int size;
+      if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
+         (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
+       {
+         devmode->dmFields |= DM_PAPERSIZE;
+         devmode->dmPaperSize = size;
+         paper_size = NULL;
+       }
+      else
+       paper_size = gtk_print_settings_get_paper_size (settings);
+    }
+  if (paper_size)
+    {
+      devmode->dmFields |= DM_PAPERSIZE;
+      devmode->dmPaperSize = paper_size_to_win32 (paper_size);
+      if (devmode->dmPaperSize == 0)
+       {
+         devmode->dmPaperSize = DMPAPER_USER;
+         devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
+
+          /* Lengths in DEVMODE are in tenths of a millimeter */
+         devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
+         devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
+       }
+      gtk_paper_size_free (paper_size);
+    }
+
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
+    {
+      devmode->dmFields |= DM_SCALE;
+      devmode->dmScale = gtk_print_settings_get_scale (settings);
+    }
+  
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
+    {
+      devmode->dmFields |= DM_COPIES;
+      devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
+    }
+
+  if (gtk_print_settings_has_key (settings, "win32-default-source"))
+    {
+      devmode->dmFields |= DM_DEFAULTSOURCE;
+      devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
+    }
+  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
+    {
+      devmode->dmFields |= DM_DEFAULTSOURCE;
+      devmode->dmDefaultSource = DMBIN_AUTO;
+
+      val = gtk_print_settings_get_default_source (settings);
+      if (strcmp (val, "auto") == 0)
+       devmode->dmDefaultSource = DMBIN_AUTO;
+      if (strcmp (val, "cassette") == 0)
+       devmode->dmDefaultSource = DMBIN_CASSETTE;
+      if (strcmp (val, "envelope") == 0)
+       devmode->dmDefaultSource = DMBIN_ENVELOPE;
+      if (strcmp (val, "envelope-manual") == 0)
+       devmode->dmDefaultSource = DMBIN_ENVMANUAL;
+      if (strcmp (val, "lower") == 0)
+       devmode->dmDefaultSource = DMBIN_LOWER;
+      if (strcmp (val, "manual") == 0)
+       devmode->dmDefaultSource = DMBIN_MANUAL;
+      if (strcmp (val, "middle") == 0)
+       devmode->dmDefaultSource = DMBIN_MIDDLE;
+      if (strcmp (val, "only-one") == 0)
+       devmode->dmDefaultSource = DMBIN_ONLYONE;
+      if (strcmp (val, "form-source") == 0)
+       devmode->dmDefaultSource = DMBIN_FORMSOURCE;
+      if (strcmp (val, "large-capacity") == 0)
+       devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
+      if (strcmp (val, "large-format") == 0)
+       devmode->dmDefaultSource = DMBIN_LARGEFMT;
+      if (strcmp (val, "tractor") == 0)
+       devmode->dmDefaultSource = DMBIN_TRACTOR;
+      if (strcmp (val, "small-format") == 0)
+       devmode->dmDefaultSource = DMBIN_SMALLFMT;
+    }
+
+  if (gtk_print_settings_has_key (settings, "win32-print-quality"))
+    {
+      devmode->dmFields |= DM_PRINTQUALITY;
+      devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
+    }
+  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
+    {
+      devmode->dmFields |= DM_PRINTQUALITY;
+      devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
+    } 
+  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
+    {
+      devmode->dmFields |= DM_PRINTQUALITY;
+      switch (gtk_print_settings_get_quality (settings))
+       {
+       case GTK_PRINT_QUALITY_LOW:
+         devmode->dmPrintQuality = DMRES_LOW;
+         break;
+       case GTK_PRINT_QUALITY_DRAFT:
+         devmode->dmPrintQuality = DMRES_DRAFT;
+         break;
+       default:
+       case GTK_PRINT_QUALITY_NORMAL:
+         devmode->dmPrintQuality = DMRES_MEDIUM;
+         break;
+       case GTK_PRINT_QUALITY_HIGH:
+         devmode->dmPrintQuality = DMRES_HIGH;
+         break;
+       }
+    }
+
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
+    {
+      devmode->dmFields |= DM_COLOR;
+      if (gtk_print_settings_get_use_color (settings))
+       devmode->dmColor = DMCOLOR_COLOR;
+      else
+       devmode->dmColor = DMCOLOR_MONOCHROME;
+    }
+
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
+    {
+      devmode->dmFields |= DM_DUPLEX;
+      switch (gtk_print_settings_get_duplex (settings))
+       {
+       default:
+       case GTK_PRINT_DUPLEX_SIMPLEX:
+         devmode->dmDuplex = DMDUP_SIMPLEX;
+         break;
+       case GTK_PRINT_DUPLEX_HORIZONTAL:
+         devmode->dmDuplex = DMDUP_HORIZONTAL;
+         break;
+       case GTK_PRINT_DUPLEX_VERTICAL:
+         devmode->dmDuplex = DMDUP_VERTICAL;
+         break;
+       }
+    }
+
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
+    {
+      devmode->dmFields |= DM_COLLATE;
+      if (gtk_print_settings_get_collate (settings))
+       devmode->dmCollate = DMCOLLATE_TRUE;
+      else
+       devmode->dmCollate = DMCOLLATE_FALSE;
+    }
+
+  if (gtk_print_settings_has_key (settings, "win32-media-type"))
+    {
+      devmode->dmFields |= DM_MEDIATYPE;
+      devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
+    }
+  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
+    {
+      devmode->dmFields |= DM_MEDIATYPE;
+      devmode->dmMediaType = DMMEDIA_STANDARD;
+      
+      val = gtk_print_settings_get_media_type (settings);
+      if (strcmp (val, "transparency") == 0)
+       devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
+      if (strcmp (val, "photographic-glossy") == 0)
+       devmode->dmMediaType = DMMEDIA_GLOSSY;
+    }
+  if (gtk_print_settings_has_key (settings, "win32-dither-type"))
+    {
+      devmode->dmFields |= DM_DITHERTYPE;
+      devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
+    }
+  else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
+    {
+      devmode->dmFields |= DM_DITHERTYPE;
+      devmode->dmDitherType = DMDITHER_FINE;
+      
+      val = gtk_print_settings_get_dither (settings);
+      if (strcmp (val, "none") == 0)
+       devmode->dmDitherType = DMDITHER_NONE;
+      if (strcmp (val, "coarse") == 0)
+       devmode->dmDitherType = DMDITHER_COARSE;
+      if (strcmp (val, "fine") == 0)
+       devmode->dmDitherType = DMDITHER_FINE;
+      if (strcmp (val, "lineart") == 0)
+       devmode->dmDitherType = DMDITHER_LINEART;
+      if (strcmp (val, "grayscale") == 0)
+       devmode->dmDitherType = DMDITHER_GRAYSCALE;
+      if (strcmp (val, "error-diffusion") == 0)
+       devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
+    }
+  
+  GlobalUnlock (hDevMode);
+
+  return hDevMode;
+}
+
+static void
+dialog_from_print_settings (GtkPrintOperation *op,
+                           LPPRINTDLGEXW printdlgex)
+{
+  GtkPrintSettings *settings = op->priv->print_settings;
+  const char *printer;
+
+  if (settings == NULL)
+    return;
+
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
+    {
+      GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
+
+      switch (print_pages)
+       {
+       default:
+       case GTK_PRINT_PAGES_SELECTION:
+       case GTK_PRINT_PAGES_ALL:
+         printdlgex->Flags |= PD_ALLPAGES;
+         break;
+       case GTK_PRINT_PAGES_CURRENT:
+         printdlgex->Flags |= PD_CURRENTPAGE;
+         break;
+       case GTK_PRINT_PAGES_RANGES:
+         printdlgex->Flags |= PD_PAGENUMS;
+         break;
+       }
+    }
+  if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
+    {
+      GtkPageRange *ranges;
+      int num_ranges, i;
+
+      ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+
+      if (num_ranges > MAX_PAGE_RANGES)
+       num_ranges = MAX_PAGE_RANGES;
+
+      printdlgex->nPageRanges = num_ranges;
+      for (i = 0; i < num_ranges; i++)
+       {
+         printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
+         printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
+       }
+    }
+  
+  /* If we have a printer saved, restore our settings */
+  printer = gtk_print_settings_get_printer (settings);
+  if (printer)
+    {
+      printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+  
+      printdlgex->hDevMode = devmode_from_settings (settings,
+                                                 op->priv->default_page_setup, NULL);
+    }
+  else
+    {
+      /* Otherwise, use the default settings */
+      DWORD FlagsCopy = printdlgex->Flags;
+      printdlgex->Flags |= PD_RETURNDEFAULT;
+      PrintDlgExW (printdlgex);
+      printdlgex->Flags = FlagsCopy;
+
+      devmode_from_settings (settings, op->priv->default_page_setup, printdlgex->hDevMode);
+    }
+}
+
+typedef struct {
+  IPrintDialogCallback iPrintDialogCallback;
+  gboolean set_hwnd;
+  int ref_count;
+} PrintDialogCallback;
+
+
+static ULONG STDMETHODCALLTYPE
+iprintdialogcallback_addref (IPrintDialogCallback *This)
+{
+  PrintDialogCallback *callback = (PrintDialogCallback *)This;
+  return ++callback->ref_count;
+}
+
+static ULONG STDMETHODCALLTYPE
+iprintdialogcallback_release (IPrintDialogCallback *This)
+{
+  PrintDialogCallback *callback = (PrintDialogCallback *)This;
+  int ref_count = --callback->ref_count;
+
+  if (ref_count == 0)
+    g_free (This);
+
+  return ref_count;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
+                                    REFIID       riid,
+                                    LPVOID      *ppvObject)
+{
+   if (IsEqualIID (riid, &IID_IUnknown) ||
+       IsEqualIID (riid, &myIID_IPrintDialogCallback))
+     {
+       *ppvObject = This;
+       IUnknown_AddRef ((IUnknown *)This);
+       return NOERROR;
+     }
+   else
+     {
+       *ppvObject = NULL;
+       return E_NOINTERFACE;
+     }
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_initdone (IPrintDialogCallback *This)
+{
+  return S_FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
+{
+  return S_FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE
+iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
+                                   HWND hDlg,
+                                   UINT uMsg,
+                                   WPARAM wParam,
+                                   LPARAM lParam,
+                                   LRESULT *pResult)
+{
+  PrintDialogCallback *callback = (PrintDialogCallback *)This;
+
+  if (!callback->set_hwnd)
+    {
+      gdk_win32_set_modal_dialog_libgtk_only (hDlg);
+      callback->set_hwnd = TRUE;
+      while (g_main_context_pending (NULL))
+        g_main_context_iteration (NULL, TRUE);
+    }
+  else if (uMsg == got_gdk_events_message)
+    {
+      while (g_main_context_pending (NULL))
+        g_main_context_iteration (NULL, TRUE);
+      *pResult = TRUE;
+      return S_OK;
+    }
+  
+  *pResult = 0;
+  return S_FALSE;
+}
+
+static IPrintDialogCallbackVtbl ipdc_vtbl = {
+  iprintdialogcallback_queryinterface,
+  iprintdialogcallback_addref,
+  iprintdialogcallback_release,
+  iprintdialogcallback_initdone,
+  iprintdialogcallback_selectionchange,
+  iprintdialogcallback_handlemessage
+};
+
+static IPrintDialogCallback *
+print_callback_new  (void)
+{
+  PrintDialogCallback *callback;
+
+  callback = g_new0 (PrintDialogCallback, 1);
+  callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
+  callback->ref_count = 1;
+  callback->set_hwnd = FALSE;
+
+  return &callback->iPrintDialogCallback;
+}
+
+static INT_PTR CALLBACK
+pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+  GtkPrintOperation *op;
+  GtkPrintOperationWin32 *op_win32;
+  
+  if (message == WM_INITDIALOG)
+    {
+      PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
+      GtkWidget *plug;
+
+      op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
+      op_win32 = op->priv->platform_data;
+      plug = g_object_new(GTK_TYPE_WIDGET, NULL);
+
+      SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
+
+      gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
+      op_win32->embed_widget = plug;
+      gtk_box_append (GTK_BOX (plug), op->priv->custom_widget);
+      gtk_widget_set_visible (op->priv->custom_widget, TRUE);
+      gtk_widget_set_visible (plug, TRUE);
+
+      /* This dialog is modal, so we grab the embed widget */
+      gtk_grab_add (plug);
+      return FALSE;
+    }
+  else if (message == WM_DESTROY)
+    {
+      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
+      op_win32 = op->priv->platform_data;
+      
+      g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
+      g_object_unref (g_object_ref_sink (op_win32->embed_widget));
+      op_win32->embed_widget = NULL;
+      op->priv->custom_widget = NULL;
+    }
+  else 
+    {
+      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
+      op_win32 = op->priv->platform_data;
+
+      /* TODO: We don't have GtkWin32EmbedWidgets anymore, but it is not currently clear
+       *       at this point what will be the proper replacement for this.  For now,
+       *       do the message handling that was in _gtk_win32_embed_widget_dialog_procedure ()
+       *       here and fill in the rest when things become clearer.
+       */
+      if (message == WM_SIZE)
+        {
+          gtk_widget_queue_resize (op_win32->embed_widget);
+    }
+
+      return FALSE;
+    }
+  
+  return FALSE;
+}
+
+static HPROPSHEETPAGE
+create_application_page (GtkPrintOperation *op)
+{
+  HPROPSHEETPAGE hpage;
+  PROPSHEETPAGEW page;
+  DLGTEMPLATE *template;
+  HGLOBAL htemplate;
+  LONG base_units;
+  WORD baseunitX, baseunitY;
+  WORD *array;
+  GtkRequisition requisition;
+  const char *tab_label;
+
+  /* Make the template the size of the custom widget size request */
+  gtk_widget_get_preferred_size (op->priv->custom_widget,
+                                 &requisition, NULL);
+
+  base_units = GetDialogBaseUnits ();
+  baseunitX = LOWORD (base_units);
+  baseunitY = HIWORD (base_units);
+  
+  htemplate = GlobalAlloc (GMEM_MOVEABLE, 
+                          sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
+  template = GlobalLock (htemplate);
+  template->style = WS_CHILDWINDOW | DS_CONTROL;
+  template->dwExtendedStyle = WS_EX_CONTROLPARENT;
+  template->cdit = 0;
+  template->x = MulDiv (0, 4, baseunitX);
+  template->y = MulDiv (0, 8, baseunitY);
+  template->cx = MulDiv (requisition.width, 4, baseunitX);
+  template->cy = MulDiv (requisition.height, 8, baseunitY);
+  
+  array = (WORD *) (template+1);
+  *array++ = 0; /* menu */
+  *array++ = 0; /* class */
+  *array++ = 0; /* title */
+  
+  memset (&page, 0, sizeof (page));
+  page.dwSize = sizeof (page);
+  page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
+  page.hInstance = NULL;
+  page.pResource = template;
+  
+  tab_label = op->priv->custom_tab_label;
+  if (tab_label == NULL)
+    tab_label = g_get_application_name ();
+  if (tab_label == NULL)
+    tab_label = _("Application");
+  page.pszTitle = g_utf8_to_utf16 (tab_label, 
+                                  -1, NULL, NULL, NULL);
+  page.pfnDlgProc = pageDlgProc;
+  page.pfnCallback = NULL;
+  page.lParam = (LPARAM) op;
+  hpage = CreatePropertySheetPageW (&page);
+  
+  GlobalUnlock (htemplate);
+  
+  /* TODO: We're leaking htemplate here... */
+  
+  return hpage;
+}
+
+static GtkPageSetup *
+create_page_setup (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPageSetup *page_setup;
+  GtkPrintSettings *settings;
+  
+  if (priv->default_page_setup)
+    page_setup = gtk_page_setup_copy (priv->default_page_setup);
+  else
+    page_setup = gtk_page_setup_new ();
+
+  settings = priv->print_settings;
+  if (settings)
+    {
+      GtkPaperSize *paper_size;
+      
+      if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+       gtk_page_setup_set_orientation (page_setup,
+                                       gtk_print_settings_get_orientation (settings));
+
+
+      paper_size = gtk_print_settings_get_paper_size (settings);
+      if (paper_size)
+       {
+         gtk_page_setup_set_paper_size (page_setup, paper_size);
+         gtk_paper_size_free (paper_size);
+       }
+
+      /* TODO: Margins? */
+    }
+  
+  return page_setup;
+}
+
+GtkPrintOperationResult
+gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
+                                       gboolean          *do_print)
+{
+  GtkPrintOperationResult result;
+  GtkPrintOperationWin32 *op_win32;
+  GtkPrintOperationPrivate *priv;
+  GtkPrintSettings *settings;
+  GtkPageSetup *page_setup;
+  DOCINFOW docinfo;
+  HGLOBAL hDevMode = NULL;
+  HGLOBAL hDevNames = NULL;
+  HDC hDC = NULL;
+  const char *printer = NULL;
+  double dpi_x, dpi_y;
+  int job_id;
+  cairo_t *cr;
+  DEVNAMES *pdn;
+  DEVMODEW *pdm;
+
+  *do_print = FALSE;
+
+  priv = op->priv;
+  settings = priv->print_settings;
+  
+  op_win32 = g_new0 (GtkPrintOperationWin32, 1);
+  priv->platform_data = op_win32;
+  priv->free_platform_data = (GDestroyNotify) op_win32_free;
+  printer = gtk_print_settings_get_printer (settings);
+
+  if (!printer)
+    {
+      /* No printer selected. Get the system default printer and store
+       * it in settings.
+       */
+      char *tmp_printer = get_default_printer ();
+      if (!tmp_printer)
+       {
+         result = GTK_PRINT_OPERATION_RESULT_ERROR;
+         g_set_error_literal (&priv->error,
+                              GTK_PRINT_ERROR,
+                              GTK_PRINT_ERROR_INTERNAL_ERROR,
+                              _("No printer found"));
+         goto out;
+       }
+      gtk_print_settings_set_printer (settings, tmp_printer);
+      printer = gtk_print_settings_get_printer (settings);
+      g_free (tmp_printer);
+    }
+
+  hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+  hDevMode = devmode_from_settings (settings, op->priv->default_page_setup, NULL);
+
+  /* Create a printer DC for the print settings and page setup provided. */
+  pdn = GlobalLock (hDevNames);
+  pdm = GlobalLock (hDevMode);
+  hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
+                  (wchar_t*)pdn + pdn->wDeviceOffset,
+                  (wchar_t*)pdn + pdn->wOutputOffset,
+                  pdm );
+  GlobalUnlock (hDevNames);
+  GlobalUnlock (hDevMode);
+
+  if (!hDC)
+    {
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                          GTK_PRINT_ERROR,
+                          GTK_PRINT_ERROR_INTERNAL_ERROR,
+                          _("Invalid argument to CreateDC"));
+      goto out;
+    }
+  
+  priv->print_context = _gtk_print_context_new (op);
+  page_setup = create_page_setup (op);
+  _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+  g_object_unref (page_setup);
+
+  *do_print = TRUE;
+
+  op_win32->surface = cairo_win32_printing_surface_create (hDC);
+  dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
+  dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
+
+  cr = cairo_create (op_win32->surface);
+  gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+  cairo_destroy (cr);
+
+  set_hard_margins (op);
+
+  memset (&docinfo, 0, sizeof (DOCINFOW));
+  docinfo.cbSize = sizeof (DOCINFOW); 
+  docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
+  docinfo.lpszOutput = NULL; 
+  docinfo.lpszDatatype = NULL; 
+  docinfo.fwType = 0; 
+
+  job_id = StartDocW (hDC, &docinfo); 
+  g_free ((void *)docinfo.lpszDocName);
+  if (job_id <= 0)
+    { 
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                          GTK_PRINT_ERROR,
+                          GTK_PRINT_ERROR_GENERAL,
+                          _("Error from StartDoc"));
+      *do_print = FALSE;
+      cairo_surface_destroy (op_win32->surface);
+      op_win32->surface = NULL;
+      goto out; 
+    }
+
+  result = GTK_PRINT_OPERATION_RESULT_APPLY;
+  op_win32->hdc = hDC;
+  op_win32->devmode = hDevMode;
+  op_win32->devnames = hDevNames;
+  op_win32->job_id = job_id;
+  op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
+  op->priv->num_page_ranges = 0;
+  if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
+    op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
+                                                               &op->priv->num_page_ranges);
+  op->priv->manual_num_copies = 1;
+  op->priv->manual_collation = FALSE;
+  op->priv->manual_reverse = FALSE;
+  op->priv->manual_orientation = FALSE;
+  op->priv->manual_scale = 1.0;
+  op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+  op->priv->manual_number_up = 1;
+  op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+
+  op->priv->start_page = win32_start_page;
+  op->priv->end_page = win32_end_page;
+  op->priv->end_run = win32_end_run;
+  
+ out:
+  if (!*do_print && hDC != NULL)
+    DeleteDC (hDC);
+
+  if (!*do_print && hDevMode != NULL)
+    GlobalFree (hDevMode);
+
+  if (!*do_print && hDevNames != NULL)
+    GlobalFree (hDevNames);
+
+  return result;
+}
+
+GtkPrintOperationResult
+gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
+                                    GtkWindow         *parent,
+                                    gboolean          *do_print)
+{
+  HRESULT hResult;
+  LPPRINTDLGEXW printdlgex = NULL;
+  LPPRINTPAGERANGE page_ranges = NULL;
+  HWND parentHWnd;
+  GtkWidget *invisible = NULL;
+  GtkPrintOperationResult result;
+  GtkPrintOperationWin32 *op_win32;
+  GtkPrintOperationPrivate *priv;
+  IPrintDialogCallback *callback;
+  HPROPSHEETPAGE prop_page;
+  static gsize common_controls_initialized = 0;
+
+  if (g_once_init_enter (&common_controls_initialized))
+    {
+      BOOL initialized;
+      INITCOMMONCONTROLSEX icc;
+
+      memset (&icc, 0, sizeof (icc));
+      icc.dwSize = sizeof (icc);
+      icc.dwICC = ICC_WIN95_CLASSES;
+
+      initialized = InitCommonControlsEx (&icc);
+      if (!initialized)
+        g_warning ("Failed to InitCommonControlsEx: %lu", GetLastError ());
+
+      _gtk_load_dll_with_libgtk3_manifest ("comdlg32.dll");
+
+      g_once_init_leave (&common_controls_initialized, initialized ? 1 : 0);
+    }
+  
+  *do_print = FALSE;
+
+  priv = op->priv;
+  
+  op_win32 = g_new0 (GtkPrintOperationWin32, 1);
+  priv->platform_data = op_win32;
+  priv->free_platform_data = (GDestroyNotify) op_win32_free;
+  
+  if (parent == NULL)
+    {
+      invisible = gtk_window_new ();
+      parentHWnd = get_parent_hwnd (invisible);
+    }
+  else
+    parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
+
+  printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
+  if (!printdlgex)
+    {
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_NOMEM,
+                           _("Not enough free memory"));
+      goto out;
+    }      
+
+  printdlgex->lStructSize = sizeof (PRINTDLGEXW);
+  printdlgex->hwndOwner = parentHWnd;
+  printdlgex->hDevMode = NULL;
+  printdlgex->hDevNames = NULL;
+  printdlgex->hDC = NULL;
+  printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
+  if (op->priv->current_page == -1)
+    printdlgex->Flags |= PD_NOCURRENTPAGE;
+  printdlgex->Flags2 = 0;
+  printdlgex->ExclusionFlags = 0;
+
+  page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR, 
+                                               MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
+  if (!page_ranges) 
+    {
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_NOMEM,
+                           _("Not enough free memory"));
+      goto out;
+    }
+
+  printdlgex->nPageRanges = 0;
+  printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
+  printdlgex->lpPageRanges = page_ranges;
+  printdlgex->nMinPage = 1;
+  if (op->priv->nr_of_pages != -1)
+    printdlgex->nMaxPage = op->priv->nr_of_pages;
+  else
+    printdlgex->nMaxPage = 10000;
+  printdlgex->nCopies = 1;
+  printdlgex->hInstance = 0;
+  printdlgex->lpPrintTemplateName = NULL;
+  printdlgex->lpCallback = NULL;
+
+  g_signal_emit_by_name (op, "create-custom-widget",
+                        &op->priv->custom_widget);
+  if (op->priv->custom_widget) {
+    prop_page = create_application_page (op);
+    printdlgex->nPropertyPages = 1;
+    printdlgex->lphPropertyPages = &prop_page;
+  } else {
+    printdlgex->nPropertyPages = 0;
+    printdlgex->lphPropertyPages = NULL;
+  }
+  
+  printdlgex->nStartPage = START_PAGE_GENERAL;
+  printdlgex->dwResultAction = 0;
+
+  dialog_from_print_settings (op, printdlgex);
+
+  callback = print_callback_new ();
+  printdlgex->lpCallback = (IUnknown *)callback;
+  got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
+
+  hResult = PrintDlgExW (printdlgex);
+  IUnknown_Release ((IUnknown *)callback);
+  gdk_win32_set_modal_dialog_libgtk_only (NULL);
+
+  if (hResult != S_OK) 
+    {
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      if (hResult == E_OUTOFMEMORY)
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_NOMEM,
+                             _("Not enough free memory"));
+      else if (hResult == E_INVALIDARG)
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid argument to PrintDlgEx"));
+      else if (hResult == E_POINTER)
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid pointer to PrintDlgEx"));
+      else if (hResult == E_HANDLE)
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid handle to PrintDlgEx"));
+      else /* E_FAIL */
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_GENERAL,
+                             _("Unspecified error"));
+      goto out;
+    }
+
+  if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
+      printdlgex->dwResultAction == PD_RESULT_APPLY)
+    {
+      result = GTK_PRINT_OPERATION_RESULT_APPLY;
+      dialog_to_print_settings (op, printdlgex);
+    }
+  else
+    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  
+  if (printdlgex->dwResultAction == PD_RESULT_PRINT)
+    {
+      DOCINFOW docinfo;
+      int job_id;
+      double dpi_x, dpi_y;
+      cairo_t *cr;
+      GtkPageSetup *page_setup;
+
+      priv->print_context = _gtk_print_context_new (op);
+      page_setup = create_page_setup (op);
+      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+      g_object_unref (page_setup);
+      
+      *do_print = TRUE;
+
+      op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
+
+      dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
+      dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
+
+      cr = cairo_create (op_win32->surface);
+      gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+      cairo_destroy (cr);
+
+      set_hard_margins (op);
+
+      memset ( &docinfo, 0, sizeof (DOCINFOW));
+      docinfo.cbSize = sizeof (DOCINFOW); 
+      docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
+      docinfo.lpszOutput = (LPCWSTR) NULL; 
+      docinfo.lpszDatatype = (LPCWSTR) NULL; 
+      docinfo.fwType = 0; 
+
+      job_id = StartDocW (printdlgex->hDC, &docinfo); 
+      g_free ((void *)docinfo.lpszDocName);
+      if (job_id <= 0) 
+       {
+         result = GTK_PRINT_OPERATION_RESULT_ERROR;
+         g_set_error_literal (&priv->error,
+                               GTK_PRINT_ERROR,
+                               GTK_PRINT_ERROR_GENERAL,
+                               _("Error from StartDoc"));
+         *do_print = FALSE;
+         cairo_surface_destroy (op_win32->surface);
+         op_win32->surface = NULL;
+         goto out; 
+       } 
+      
+      op_win32->hdc = printdlgex->hDC;
+      op_win32->devmode = printdlgex->hDevMode;
+      op_win32->devnames = printdlgex->hDevNames;
+      op_win32->job_id = job_id;
+      
+      op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
+      op->priv->num_page_ranges = 0;
+      if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
+       op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
+                                                                   &op->priv->num_page_ranges);
+      op->priv->manual_num_copies = printdlgex->nCopies;
+      op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
+      op->priv->manual_reverse = FALSE;
+      op->priv->manual_orientation = FALSE;
+      op->priv->manual_scale = 1.0;
+      op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+      op->priv->manual_number_up = 1;
+      op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+    }
+
+  op->priv->start_page = win32_start_page;
+  op->priv->end_page = win32_end_page;
+  op->priv->end_run = win32_end_run;
+  
+  out:
+  if (!*do_print && printdlgex && printdlgex->hDC != NULL)
+    DeleteDC (printdlgex->hDC);
+
+  if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) 
+    GlobalFree (printdlgex->hDevMode); 
+
+  if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) 
+    GlobalFree (printdlgex->hDevNames); 
+
+  if (page_ranges)
+    GlobalFree (page_ranges);
+
+  if (printdlgex)
+    GlobalFree (printdlgex);
+
+  if (invisible)
+    gtk_window_destroy (GTK_WINDOW (invisible));
+
+  return result;
+}
+
+GtkPrintOperationResult
+_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+                                                 gboolean           show_dialog,
+                                                 GtkWindow         *parent,
+                                                 gboolean          *do_print)
+{
+  if (show_dialog)
+    return gtk_print_operation_run_with_dialog (op, parent, do_print);
+  else
+    return gtk_print_operation_run_without_dialog (op, do_print);
+}
+
+void
+_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+                                                     cairo_surface_t   *surface,
+                                                     GtkWindow         *parent,
+                                                     const char        *filename)
+{
+  HDC dc;
+  HENHMETAFILE metafile;
+  
+  dc = cairo_win32_surface_get_dc (surface);
+  cairo_surface_destroy (surface);
+  metafile = CloseEnhMetaFile (dc);
+  DeleteEnhMetaFile (metafile);
+  
+  ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+                                                         cairo_surface_t *surface,
+                                                         cairo_t *cr)
+{
+  HDC dc = cairo_win32_surface_get_dc (surface);
+  StartPage (dc);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+                                                       cairo_surface_t *surface,
+                                                       cairo_t *cr)
+{
+  HDC dc;
+
+  cairo_surface_show_page (surface);
+
+  /* TODO: Enhanced metafiles don't support multiple pages.
+   */
+  dc = cairo_win32_surface_get_dc (surface);
+  EndPage (dc);
+}
+
+cairo_surface_t *
+_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             double            *dpi_x,
+                                                             double            *dpi_y,
+                                                             char             **target)
+{
+  GtkPaperSize *paper_size;
+  HDC metafile_dc;
+  RECT rect;
+  char *template;
+  char *filename;
+  gunichar2 *filename_utf16;
+  int fd;
+
+  template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
+  fd = g_mkstemp (template);
+  close (fd);
+
+  filename = g_strconcat (template, ".emf", NULL);
+  g_free (template);
+  
+  filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+  g_free (filename);
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+
+  /* The rectangle dimensions are given in hundredths of a millimeter */
+  rect.left = 0;
+  rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
+  rect.top = 0;
+  rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
+  
+  metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
+                                   &rect, L"Gtk+\0Print Preview\0\0");
+  if (metafile_dc == NULL)
+    {
+      g_warning ("Can't create metafile");
+      return NULL;
+    }
+
+  *target = (char *)filename_utf16;
+  
+  *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
+  *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
+
+  return cairo_win32_printing_surface_create (metafile_dc);
+}
+
+void
+_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             cairo_surface_t   *surface)
+{
+  /* TODO: Implement */
+}
+
+/**
+ * gtk_print_run_page_setup_dialog:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ *
+ * Runs a page setup dialog, letting the user modify the values from
+ * @page_setup. If the user cancels the dialog, the returned `GtkPageSetup`
+ * is identical to the passed in @page_setup, otherwise it contains the
+ * modifications done in the dialog.
+ *
+ * Note that this function may use a recursive mainloop to show the page
+ * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is
+ * a problem.
+ *
+ * Returns: (transfer full): a new `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_print_run_page_setup_dialog (GtkWindow        *parent,
+                                GtkPageSetup     *page_setup,
+                                GtkPrintSettings *settings)
+{
+  LPPAGESETUPDLGW pagesetupdlg = NULL;
+  BOOL res;
+  gboolean free_settings;
+  const char *printer;
+  GtkPaperSize *paper_size;
+  DWORD measure_system;
+  GtkUnit unit;
+  double scale;
+
+  pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
+  if (!pagesetupdlg)
+    return NULL;
+
+  free_settings = FALSE;
+  if (settings == NULL)
+    {
+      settings = gtk_print_settings_new ();
+      free_settings = TRUE;
+    }
+  
+  memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
+
+  pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
+
+  if (parent != NULL)
+    pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
+  else
+    pagesetupdlg->hwndOwner = NULL;
+
+  pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
+  pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup, NULL);
+  pagesetupdlg->hDevNames = NULL;
+  printer = gtk_print_settings_get_printer (settings);
+  if (printer)
+    pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+
+  GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
+                 (LPWSTR)&measure_system, sizeof (DWORD));
+
+  if (measure_system == 0)
+    {
+      pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
+      unit = GTK_UNIT_MM;
+      scale = 100;
+    }
+  else
+    {
+      pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
+      unit = GTK_UNIT_INCH;
+      scale = 1000;
+    }
+
+  /* This is the object we return, we allocate it here so that
+   * we can use the default page margins */
+  if (page_setup)
+    page_setup = gtk_page_setup_copy (page_setup);
+  else
+    page_setup = gtk_page_setup_new ();
+  
+  pagesetupdlg->Flags |= PSD_MARGINS;
+  pagesetupdlg->rtMargin.left =
+    floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
+  pagesetupdlg->rtMargin.right =
+    floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
+  pagesetupdlg->rtMargin.top = 
+    floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
+  pagesetupdlg->rtMargin.bottom =
+    floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
+
+  pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
+  pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
+  got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
+  
+  res = PageSetupDlgW (pagesetupdlg);
+  gdk_win32_set_modal_dialog_libgtk_only (NULL);
+
+  if (res)
+    {  
+      if (pagesetupdlg->hDevNames != NULL)
+       devnames_to_settings (settings, pagesetupdlg->hDevNames);
+
+      if (pagesetupdlg->hDevMode != NULL)
+       devmode_to_settings (settings, pagesetupdlg->hDevMode);
+    }
+  
+  if (res)
+    {
+      gtk_page_setup_set_orientation (page_setup, 
+                                     gtk_print_settings_get_orientation (settings));
+      paper_size = gtk_print_settings_get_paper_size (settings);
+      if (paper_size)
+       {
+         gtk_page_setup_set_paper_size (page_setup, paper_size);
+         gtk_paper_size_free (paper_size);
+       }
+
+      if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
+       {
+         unit = GTK_UNIT_MM;
+         scale = 100;
+       }
+      else
+       {
+         unit = GTK_UNIT_INCH;
+         scale = 1000;
+       }
+
+      gtk_page_setup_set_left_margin (page_setup,
+                                     pagesetupdlg->rtMargin.left / scale,
+                                     unit);
+      gtk_page_setup_set_right_margin (page_setup,
+                                      pagesetupdlg->rtMargin.right / scale,
+                                      unit);
+      gtk_page_setup_set_top_margin (page_setup,
+                                    pagesetupdlg->rtMargin.top / scale,
+                                    unit);
+      gtk_page_setup_set_bottom_margin (page_setup,
+                                       pagesetupdlg->rtMargin.bottom / scale,
+                                       unit);
+    }
+  
+  if (free_settings)
+    g_object_unref (settings);
+
+  return page_setup;
+}
+
+/**
+ * gtk_print_run_page_setup_dialog_async:
+ * @parent: (nullable): transient parent
+ * @page_setup: (nullable): an existing `GtkPageSetup`
+ * @settings: a `GtkPrintSettings`
+ * @done_cb: (scope async): a function to call when the user saves
+ *    the modified page setup
+ * @data: user data to pass to @done_cb
+ *
+ * Runs a page setup dialog, letting the user modify the values from @page_setup.
+ *
+ * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after
+ * showing the page setup dialog on platforms that support this, and calls @done_cb
+ * from a signal handler for the ::response signal of the dialog.
+ */
+void
+gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
+                                      GtkPageSetup         *page_setup,
+                                      GtkPrintSettings     *settings,
+                                      GtkPageSetupDoneFunc  done_cb,
+                                      gpointer              data)
+{
+  GtkPageSetup *new_page_setup;
+
+  new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
+  done_cb (new_page_setup, data);
+  g_object_unref (new_page_setup);
+}
diff --git a/gtk/print/gtkprintunixdialog.c b/gtk/print/gtkprintunixdialog.c
new file mode 100644 (file)
index 0000000..1835002
--- /dev/null
@@ -0,0 +1,3564 @@
+/* GtkPrintUnixDialog
+ * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
+ * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
+ * Copyright © 2006, 2007 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "gtkprintunixdialog.h"
+
+#include "gtkcustompaperunixdialog.h"
+#include "gtkprintbackendprivate.h"
+#include "gtkprinterprivate.h"
+#include "gtkprinteroptionwidgetprivate.h"
+#include "gtkprintutilsprivate.h"
+
+#include "gtkspinbutton.h"
+#include "gtkimage.h"
+#include "gtknotebook.h"
+#include "gtkscrolledwindow.h"
+#include "gtktogglebutton.h"
+#include "gtkdrawingarea.h"
+#include "gtkbox.h"
+#include "gtkgrid.h"
+#include "gtkframe.h"
+#include "gtklabel.h"
+#include "gtkbuildable.h"
+#include "deprecated/gtkmessagedialog.h"
+#include "gtkbutton.h"
+#include "gtksnapshot.h"
+#include "gtkrenderbackgroundprivate.h"
+#include "gtkrenderborderprivate.h"
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+#include "gtktypebuiltins.h"
+#include "deprecated/gtkdialogprivate.h"
+#include "gtkwidgetprivate.h"
+#include "gtkcsscolorvalueprivate.h"
+
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+/**
+ * GtkPrintUnixDialog:
+ *
+ * `GtkPrintUnixDialog` implements a print dialog for platforms
+ * which don’t provide a native print dialog, like Unix.
+ *
+ * ![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
+ * <object class="GtkPrintUnixDialog" id="dialog1">
+ *   <child internal-child="notebook">
+ *     <object class="GtkNotebook" id="notebook">
+ *       <child>
+ *         <object type="GtkNotebookPage">
+ *           <property name="tab_expand">False</property>
+ *           <property name="tab_fill">False</property>
+ *           <property name="tab">
+ *             <object class="GtkLabel" id="tablabel">
+ *               <property name="label">Tab label</property>
+ *             </object>
+ *           </property>
+ *           <property name="child">
+ *             <object class="GtkLabel" id="tabcontent">
+ *               <property name="label">Content on notebook tab</property>
+ *             </object>
+ *           </property>
+ *         </object>
+ *       </child>
+ *     </object>
+ *   </child>
+ * </object>
+ * ```
+ *
+ * # CSS nodes
+ *
+ * `GtkPrintUnixDialog` has a single CSS node with name window. The style classes
+ * dialog and print are added.
+ */
+
+
+#define EXAMPLE_PAGE_AREA_SIZE 110
+#define RULER_DISTANCE 7.5
+#define RULER_RADIUS 2
+
+
+static void     gtk_print_unix_dialog_constructed  (GObject            *object);
+static void     gtk_print_unix_dialog_dispose      (GObject            *object);
+static void     gtk_print_unix_dialog_finalize     (GObject            *object);
+static void     gtk_print_unix_dialog_set_property (GObject            *object,
+                                                    guint               prop_id,
+                                                    const GValue       *value,
+                                                    GParamSpec         *pspec);
+static void     gtk_print_unix_dialog_get_property (GObject            *object,
+                                                    guint               prop_id,
+                                                    GValue             *value,
+                                                    GParamSpec         *pspec);
+static void     unschedule_idle_mark_conflicts     (GtkPrintUnixDialog *dialog);
+static void     selected_printer_changed           (GtkPrintUnixDialog *dialog);
+static void     clear_per_printer_ui               (GtkPrintUnixDialog *dialog);
+static void     printer_added_cb                   (GListModel         *model,
+                                                    guint               position,
+                                                    guint               removed,
+                                                    guint               added,
+                                                    GtkPrintUnixDialog *dialog);
+static void     printer_status_cb                  (GtkPrintBackend    *backend,
+                                                    GtkPrinter         *printer,
+                                                    GtkPrintUnixDialog *dialog);
+static void     update_collate_icon                (GtkToggleButton    *toggle_button,
+                                                    GtkPrintUnixDialog *dialog);
+static void     error_dialogs                      (GtkPrintUnixDialog *print_dialog,
+                                                   int                 print_dialog_response_id,
+                                                   gpointer            data);
+static gboolean page_range_entry_focus_changed     (GtkWidget          *entry,
+                                                    GParamSpec         *pspec,
+                                                    GtkPrintUnixDialog *dialog);
+static void     update_page_range_entry_sensitivity(GtkWidget          *button,
+                                                   GtkPrintUnixDialog *dialog);
+static void     update_print_at_entry_sensitivity  (GtkWidget          *button,
+                                                   GtkPrintUnixDialog *dialog);
+static void     update_print_at_option             (GtkPrintUnixDialog *dialog);
+static void     update_dialog_from_capabilities    (GtkPrintUnixDialog *dialog);
+static void     draw_collate                       (GtkDrawingArea     *da,
+                                                   cairo_t            *cr,
+                                                    int                 width,
+                                                    int                 height,
+                                                    gpointer            data);
+static gboolean is_printer_active                  (gpointer            item,
+                                                    gpointer            data);
+static  int     default_printer_list_sort_func     (gconstpointer        a,
+                                                    gconstpointer        b,
+                                                   gpointer             user_data);
+static void     update_number_up_layout            (GtkPrintUnixDialog  *dialog);
+static void     draw_page                          (GtkDrawingArea      *da,
+                                                   cairo_t             *cr,
+                                                    int                  width,
+                                                    int                  height,
+                                                    gpointer             data);
+
+
+static gboolean dialog_get_collate                 (GtkPrintUnixDialog *dialog);
+static gboolean dialog_get_reverse                 (GtkPrintUnixDialog *dialog);
+static int      dialog_get_n_copies                (GtkPrintUnixDialog *dialog);
+
+static gboolean set_active_printer                 (GtkPrintUnixDialog *dialog,
+                                                    const char         *printer_name);
+static void redraw_page_layout_preview             (GtkPrintUnixDialog *dialog);
+static GListModel *load_print_backends             (GtkPrintUnixDialog *dialog);
+
+/* GtkBuildable */
+static void gtk_print_unix_dialog_buildable_init                    (GtkBuildableIface *iface);
+static GObject *gtk_print_unix_dialog_buildable_get_internal_child  (GtkBuildable *buildable,
+                                                                     GtkBuilder   *builder,
+                                                                     const char   *childname);
+
+static const char common_paper_sizes[][16] = {
+  "na_letter",
+  "na_legal",
+  "iso_a4",
+  "iso_a5",
+  "roc_16k",
+  "iso_b5",
+  "jis_b5",
+  "na_number-10",
+  "iso_dl",
+  "jpn_chou3",
+  "na_ledger",
+  "iso_a3",
+};
+
+/* Keep in line with liststore defined in gtkprintunixdialog.ui */
+enum {
+  PAGE_SETUP_LIST_COL_PAGE_SETUP,
+  PAGE_SETUP_LIST_COL_IS_SEPARATOR,
+  PAGE_SETUP_LIST_N_COLS
+};
+
+/* Keep in line with liststore defined in gtkprintunixdialog.ui */
+enum {
+  PRINTER_LIST_COL_ICON,
+  PRINTER_LIST_COL_NAME,
+  PRINTER_LIST_COL_STATE,
+  PRINTER_LIST_COL_JOBS,
+  PRINTER_LIST_COL_LOCATION,
+  PRINTER_LIST_COL_PRINTER_OBJ,
+  PRINTER_LIST_N_COLS
+};
+
+enum {
+  PROP_0,
+  PROP_PAGE_SETUP,
+  PROP_CURRENT_PAGE,
+  PROP_PRINT_SETTINGS,
+  PROP_SELECTED_PRINTER,
+  PROP_MANUAL_CAPABILITIES,
+  PROP_SUPPORT_SELECTION,
+  PROP_HAS_SELECTION,
+  PROP_EMBED_PAGE_SETUP
+};
+
+typedef struct _GtkPrintUnixDialogClass    GtkPrintUnixDialogClass;
+
+struct _GtkPrintUnixDialog
+{
+  GtkDialog parent_instance;
+
+  GtkWidget *notebook;
+
+  GtkWidget *printer_list;
+
+  GtkPrintCapabilities manual_capabilities;
+  GtkPrintCapabilities printer_capabilities;
+
+  GtkPageSetup *page_setup;
+  gboolean page_setup_set;
+  gboolean embed_page_setup;
+  GListStore *page_setup_list;
+  GListStore *custom_paper_list;
+  GListStore *manage_papers_list;
+
+  gboolean support_selection;
+  gboolean has_selection;
+
+  GtkWidget *all_pages_radio;
+  GtkWidget *current_page_radio;
+  GtkWidget *selection_radio;
+  GtkWidget *range_table;
+  GtkWidget *page_range_radio;
+  GtkWidget *page_range_entry;
+
+  GtkWidget *copies_spin;
+  GtkWidget *collate_check;
+  GtkWidget *reverse_check;
+  GtkWidget *collate_image;
+  GtkWidget *page_layout_preview;
+  GtkWidget *scale_spin;
+  GtkWidget *page_set_combo;
+  GtkWidget *print_now_radio;
+  GtkWidget *print_at_radio;
+  GtkWidget *print_at_entry;
+  GtkWidget *print_hold_radio;
+  GtkWidget *paper_size_combo;
+  GtkWidget *orientation_combo;
+  gboolean internal_page_setup_change;
+  gboolean updating_print_at;
+  GtkPrinterOptionWidget *pages_per_sheet;
+  GtkPrinterOptionWidget *duplex;
+  GtkPrinterOptionWidget *paper_type;
+  GtkPrinterOptionWidget *paper_source;
+  GtkPrinterOptionWidget *output_tray;
+  GtkPrinterOptionWidget *job_prio;
+  GtkPrinterOptionWidget *billing_info;
+  GtkPrinterOptionWidget *cover_before;
+  GtkPrinterOptionWidget *cover_after;
+  GtkPrinterOptionWidget *number_up_layout;
+
+  GtkWidget *conflicts_widget;
+
+  GtkWidget *job_page;
+  GtkWidget *finishing_table;
+  GtkWidget *finishing_page;
+  GtkWidget *image_quality_table;
+  GtkWidget *image_quality_page;
+  GtkWidget *color_table;
+  GtkWidget *color_page;
+
+  GtkWidget *advanced_vbox;
+  GtkWidget *advanced_page;
+
+  GtkWidget *extension_point;
+
+  /* These are set initially on selected printer (either default printer,
+   * printer taken from set settings, or user-selected), but when any
+   * setting is changed by the user it is cleared.
+   */
+  GtkPrintSettings *initial_settings;
+
+  GtkPrinterOption *number_up_layout_n_option;
+  GtkPrinterOption *number_up_layout_2_option;
+
+  /* This is the initial printer set by set_settings. We look for it in
+   * the added printers. We clear this whenever the user manually changes
+   * to another printer, when the user changes a setting or when we find
+   * this printer.
+   */
+  char *waiting_for_printer;
+  gboolean internal_printer_change;
+
+  GList *print_backends;
+
+  GtkPrinter *current_printer;
+  GtkPrinter *request_details_printer;
+  gulong request_details_tag;
+  GtkPrinterOptionSet *options;
+  gulong options_changed_handler;
+  gulong mark_conflicts_id;
+
+  char *format_for_printer;
+
+  int current_page;
+  GtkCssNode *collate_paper_node;
+  GtkCssNode *page_layout_paper_node;
+};
+
+struct _GtkPrintUnixDialogClass
+{
+  GtkDialogClass parent_class;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_print_unix_dialog_buildable_init))
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static gboolean
+is_default_printer (GtkPrintUnixDialog *dialog,
+                    GtkPrinter         *printer)
+{
+  if (dialog->format_for_printer)
+    return strcmp (dialog->format_for_printer,
+                   gtk_printer_get_name (printer)) == 0;
+ else
+   return gtk_printer_is_default (printer);
+}
+
+static void
+gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = (GObjectClass *) class;
+  widget_class = (GtkWidgetClass *) class;
+
+  object_class->constructed = gtk_print_unix_dialog_constructed;
+  object_class->finalize = gtk_print_unix_dialog_finalize;
+  object_class->dispose = gtk_print_unix_dialog_dispose;
+  object_class->set_property = gtk_print_unix_dialog_set_property;
+  object_class->get_property = gtk_print_unix_dialog_get_property;
+
+  /**
+   * GtkPrintUnixDialog:page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_page_setup)
+   *
+   * The `GtkPageSetup` object to use.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PAGE_SETUP,
+                                   g_param_spec_object ("page-setup", NULL, NULL,
+                                                        GTK_TYPE_PAGE_SETUP,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintUnixDialog:current-page: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_current_page org.gtk.Property.set=gtk_print_unix_dialog_set_current_page)
+   *
+   * The current page in the document.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_CURRENT_PAGE,
+                                   g_param_spec_int ("current-page", NULL, NULL,
+                                                     -1,
+                                                     G_MAXINT,
+                                                     -1,
+                                                     GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintUnixDialog:print-settings: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_settings org.gtk.Property.set=gtk_print_unix_dialog_set_settings)
+   *
+   * The `GtkPrintSettings` object used for this dialog.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_PRINT_SETTINGS,
+                                   g_param_spec_object ("print-settings", NULL, NULL,
+                                                        GTK_TYPE_PRINT_SETTINGS,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintUnixDialog:selected-printer: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_selected_printer)
+   *
+   * The `GtkPrinter` which is selected.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_SELECTED_PRINTER,
+                                   g_param_spec_object ("selected-printer", NULL, NULL,
+                                                        GTK_TYPE_PRINTER,
+                                                        GTK_PARAM_READABLE));
+
+  /**
+   * GtkPrintUnixDialog:manual-capabilities: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_manual_capabilities org.gtk.Property.set=gtk_print_unix_dialog_set_manual_capabilities)
+   *
+   * Capabilities the application can handle.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_MANUAL_CAPABILITIES,
+                                   g_param_spec_flags ("manual-capabilities", NULL, NULL,
+                                                       GTK_TYPE_PRINT_CAPABILITIES,
+                                                       0,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintUnixDialog:support-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_support_selection org.gtk.Property.set=gtk_print_unix_dialog_set_support_selection)
+   *
+   * Whether the dialog supports selection.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_SUPPORT_SELECTION,
+                                   g_param_spec_boolean ("support-selection", NULL, NULL,
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintUnixDialog:has-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_has_selection org.gtk.Property.set=gtk_print_unix_dialog_set_has_selection)
+   *
+   * Whether the application has a selection.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_HAS_SELECTION,
+                                   g_param_spec_boolean ("has-selection", NULL, NULL,
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+   /**
+    * GtkPrintUnixDialog:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_embed_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_embed_page_setup)
+    *
+    * %TRUE if the page setup controls are embedded.
+    */
+   g_object_class_install_property (object_class,
+                                   PROP_EMBED_PAGE_SETUP,
+                                   g_param_spec_boolean ("embed-page-setup", NULL, NULL,
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /* Bind class to template
+   */
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                              "/org/gtk/libgtk/ui/gtkprintunixdialog.ui");
+
+  /* GtkTreeView / GtkTreeModel */
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, printer_list);
+
+  /* General Widgetry */
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, notebook);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, current_page_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, selection_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, range_table);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_entry);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, copies_spin);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_check);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, reverse_check);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_image);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_layout_preview);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, scale_spin);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_set_combo);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_now_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_entry);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_hold_radio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_size_combo);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, orientation_combo);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, conflicts_widget);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_page);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_table);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_page);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_table);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_page);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_table);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_page);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_vbox);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_page);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, extension_point);
+
+  /* GtkPrinterOptionWidgets... */
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, pages_per_sheet);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, duplex);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_type);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_source);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, output_tray);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_prio);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, billing_info);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_before);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_after);
+  gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, number_up_layout);
+
+  /* Callbacks handled in the UI */
+  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+  gtk_widget_class_bind_template_callback (widget_class, error_dialogs);
+  gtk_widget_class_bind_template_callback (widget_class, page_range_entry_focus_changed);
+  gtk_widget_class_bind_template_callback (widget_class, update_page_range_entry_sensitivity);
+  gtk_widget_class_bind_template_callback (widget_class, update_print_at_entry_sensitivity);
+  gtk_widget_class_bind_template_callback (widget_class, update_print_at_option);
+  gtk_widget_class_bind_template_callback (widget_class, update_dialog_from_capabilities);
+  gtk_widget_class_bind_template_callback (widget_class, update_collate_icon);
+  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+  gtk_widget_class_bind_template_callback (widget_class, update_number_up_layout);
+  gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
+}
+
+/* Returns a toplevel GtkWindow, or NULL if none */
+static GtkWindow *
+get_toplevel (GtkWidget *widget)
+{
+  GtkWidget *toplevel = NULL;
+
+  toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
+  if (GTK_IS_WINDOW (toplevel))
+    return GTK_WINDOW (toplevel);
+  else
+    return NULL;
+}
+
+static void
+set_busy_cursor (GtkPrintUnixDialog *dialog,
+                 gboolean            busy)
+{
+  GtkWidget *widget;
+  GtkWindow *toplevel;
+
+  toplevel = get_toplevel (GTK_WIDGET (dialog));
+  widget = GTK_WIDGET (toplevel);
+
+  if (!toplevel || !gtk_widget_get_realized (widget))
+    return;
+
+  if (busy)
+    gtk_widget_set_cursor_from_name (widget, "progress");
+  else
+    gtk_widget_set_cursor (widget, NULL);
+}
+
+typedef struct {
+  GMainLoop *loop;
+  int response;
+} ConfirmationData;
+
+static void
+on_confirmation_dialog_response (GtkWidget *dialog,
+                                 int        response,
+                                 gpointer   user_data)
+{
+  ConfirmationData *data = user_data;
+
+  data->response = response;
+
+  g_main_loop_quit (data->loop);
+
+  gtk_window_destroy (GTK_WINDOW (dialog));
+}
+
+/* This function handles error messages before printing.
+ */
+static void
+error_dialogs (GtkPrintUnixDialog *dialog,
+               int                 dialog_response_id,
+               gpointer            data)
+{
+  if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK)
+    {
+      GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog);
+
+      if (printer != NULL)
+        {
+          if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer))
+            {
+              g_signal_stop_emission_by_name (dialog, "response");
+              return;
+            }
+
+          /* Shows overwrite confirmation dialog in the case of printing
+           * to file which already exists.
+           */
+          if (gtk_printer_is_virtual (printer))
+            {
+              GtkPrinterOption *option =
+                gtk_printer_option_set_lookup (dialog->options,
+                                               "gtk-main-page-custom-input");
+
+              if (option != NULL &&
+                  option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
+                {
+                  GFile *file = g_file_new_for_uri (option->value);
+
+                  if (g_file_query_exists (file, NULL))
+                    {
+                      GtkWidget *message_dialog;
+                      GtkWindow *toplevel;
+                      char *basename;
+                      char *dirname;
+                      GFile *parent;
+
+                      toplevel = get_toplevel (GTK_WIDGET (dialog));
+
+                      basename = g_file_get_basename (file);
+                      parent = g_file_get_parent (file);
+                      dirname = g_file_get_parse_name (parent);
+                      g_object_unref (parent);
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+                      message_dialog = gtk_message_dialog_new (toplevel,
+                                                               GTK_DIALOG_MODAL |
+                                                               GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                               GTK_MESSAGE_QUESTION,
+                                                               GTK_BUTTONS_NONE,
+                                                               _("A file named “%s” already exists.  Do you want to replace it?"),
+                                                               basename);
+
+                      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
+                                                                _("The file already exists in “%s”.  Replacing it will "
+                                                                "overwrite its contents."),
+                                                                dirname);
+
+                      gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+                                             _("_Cancel"),
+                                             GTK_RESPONSE_CANCEL);
+                      gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+                                             _("_Replace"),
+                                             GTK_RESPONSE_ACCEPT);
+                      gtk_dialog_set_default_response (GTK_DIALOG (message_dialog),
+                                                       GTK_RESPONSE_ACCEPT);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+                      if (gtk_window_has_group (toplevel))
+                        gtk_window_group_add_window (gtk_window_get_group (toplevel),
+                                                     GTK_WINDOW (message_dialog));
+
+                      gtk_window_present (GTK_WINDOW (message_dialog));
+
+                      /* Block on the confirmation dialog until we have a response,
+                       * so that we can stop the "response" signal emission on the
+                       * print dialog
+                       */
+                      ConfirmationData cdata;
+
+                      cdata.loop = g_main_loop_new (NULL, FALSE);
+                      cdata.response = 0;
+
+                      g_signal_connect (message_dialog, "response",
+                                        G_CALLBACK (on_confirmation_dialog_response),
+                                        &cdata);
+
+                      g_main_loop_run (cdata.loop);
+                      g_main_loop_unref (cdata.loop);
+
+                      g_free (dirname);
+                      g_free (basename);
+
+                      if (cdata.response != GTK_RESPONSE_ACCEPT)
+                        g_signal_stop_emission_by_name (dialog, "response");
+                    }
+
+                  g_object_unref (file);
+                }
+            }
+        }
+    }
+}
+
+static char *
+get_printer_key (GtkPrinter *printer)
+{
+  return g_strconcat ("", gtk_printer_get_name (printer), " ", gtk_printer_get_location (printer), NULL);
+}
+
+static void
+setup_paper_size_item (GtkSignalListItemFactory *factory,
+                       GtkListItem              *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new ("");
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_paper_size_list_item (GtkSignalListItemFactory *factory,
+                           GtkListItem              *item,
+                           GtkPrintUnixDialog       *self)
+{
+  GtkPageSetup *page_setup;
+  GtkWidget *label;
+  guint pos;
+  GListModel *papers;
+  GListModel *model;
+  gpointer first;
+
+  page_setup = gtk_list_item_get_item (item);
+  label = gtk_list_item_get_child (item);
+
+  pos = gtk_list_item_get_position (item);
+  papers = gtk_drop_down_get_model (GTK_DROP_DOWN (self->paper_size_combo));
+  model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), pos);
+  if (model != G_LIST_MODEL (self->manage_papers_list))
+    {
+      GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
+      gtk_label_set_text (GTK_LABEL (label), gtk_paper_size_get_display_name (paper_size));
+    }
+  else
+    gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
+
+  first = g_list_model_get_item (model, 0);
+  g_object_unref (first);
+  if (pos != 0 &&
+      page_setup == GTK_PAGE_SETUP (first))
+    gtk_widget_add_css_class (gtk_widget_get_parent (label), "separator");
+  else
+    gtk_widget_remove_css_class (gtk_widget_get_parent (label), "separator");
+}
+
+static void
+bind_paper_size_item (GtkSignalListItemFactory *factory,
+                      GtkListItem              *item,
+                      GtkPrintUnixDialog       *self)
+{
+  GtkWidget *label;
+
+  bind_paper_size_list_item (factory, item, self);
+
+  label = gtk_list_item_get_child (item);
+  gtk_widget_remove_css_class (label, "separator-before");
+}
+
+static void
+gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
+{
+  GtkWidget *widget;
+  GListModel *model;
+  GListModel *sorted;
+  GListModel *filtered;
+  GListModel *selection;
+  GtkSorter *sorter;
+  GtkFilter *filter;
+  GtkStringFilter *filter1;
+  GtkCustomFilter *filter2;
+  GtkListItemFactory *factory;
+  GListStore *store;
+  GListModel *paper_size_list;
+  GtkPageSetup *page_setup;
+
+  dialog->print_backends = NULL;
+  dialog->current_page = -1;
+  dialog->number_up_layout_n_option = NULL;
+  dialog->number_up_layout_2_option = NULL;
+
+  dialog->page_setup = gtk_page_setup_new ();
+  dialog->page_setup_set = FALSE;
+  dialog->embed_page_setup = FALSE;
+  dialog->internal_page_setup_change = FALSE;
+  dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
+  page_setup = gtk_page_setup_new ();
+  g_list_store_append (dialog->manage_papers_list, page_setup);
+  g_object_unref (page_setup);
+
+  dialog->support_selection = FALSE;
+  dialog->has_selection = FALSE;
+
+  g_type_ensure (GTK_TYPE_PRINTER);
+  g_type_ensure (GTK_TYPE_PRINTER_OPTION);
+  g_type_ensure (GTK_TYPE_PRINTER_OPTION_SET);
+  g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
+
+  gtk_widget_init_template (GTK_WIDGET (dialog));
+  gtk_widget_add_css_class (GTK_WIDGET (dialog), "print");
+
+  gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          _("Pre_view"), GTK_RESPONSE_APPLY,
+                          _("_Cancel"), GTK_RESPONSE_CANCEL,
+                          _("_Print"), GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  widget = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_widget_set_sensitive (widget, FALSE);
+
+  gtk_widget_set_visible (dialog->selection_radio, FALSE);
+  gtk_widget_set_visible (dialog->conflicts_widget, FALSE);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+  g_object_unref (factory);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
+  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (dialog->paper_size_combo), factory);
+  g_object_unref (factory);
+
+  store = g_list_store_new (G_TYPE_LIST_MODEL);
+  g_list_store_append (store, dialog->page_setup_list);
+  g_list_store_append (store, dialog->custom_paper_list);
+  g_list_store_append (store, dialog->manage_papers_list);
+  paper_size_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (store)));
+  gtk_drop_down_set_model (GTK_DROP_DOWN (dialog->paper_size_combo), paper_size_list);
+  g_object_unref (paper_size_list);
+
+  /* Load backends */
+  model = load_print_backends (dialog);
+  sorter = GTK_SORTER (gtk_custom_sorter_new (default_printer_list_sort_func, NULL, NULL));
+  sorted = G_LIST_MODEL (gtk_sort_list_model_new (model, sorter));
+
+  filter = GTK_FILTER (gtk_every_filter_new ());
+
+  filter1 = gtk_string_filter_new (
+                gtk_cclosure_expression_new (G_TYPE_STRING,
+                                             NULL, 0, NULL,
+                                             G_CALLBACK (get_printer_key),
+                                             NULL, NULL));
+  gtk_string_filter_set_match_mode (filter1, GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
+  gtk_string_filter_set_ignore_case (filter1, TRUE);
+  gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter1));
+
+  filter2 = gtk_custom_filter_new (is_printer_active, dialog, NULL);
+  gtk_multi_filter_append (GTK_MULTI_FILTER (filter), GTK_FILTER (filter2));
+
+  filtered = G_LIST_MODEL (gtk_filter_list_model_new (sorted, filter));
+
+  selection = G_LIST_MODEL (gtk_single_selection_new (filtered));
+  gtk_single_selection_set_autoselect (GTK_SINGLE_SELECTION (selection), FALSE);
+  gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (selection), GTK_INVALID_LIST_POSITION);
+  gtk_column_view_set_model (GTK_COLUMN_VIEW (dialog->printer_list), GTK_SELECTION_MODEL (selection));
+  g_signal_connect (selection, "items-changed", G_CALLBACK (printer_added_cb), dialog);
+  g_signal_connect_swapped (selection, "notify::selected", G_CALLBACK (selected_printer_changed), dialog);
+  g_object_unref (selection);
+
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+
+  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->collate_image),
+                                  draw_collate,
+                                  dialog, NULL);
+  gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->page_layout_preview),
+                                  draw_page,
+                                  dialog, NULL);
+
+  gtk_css_node_set_name (gtk_widget_get_css_node (dialog->collate_image), g_quark_from_static_string ("drawing"));
+  gtk_css_node_set_name (gtk_widget_get_css_node (dialog->page_layout_preview), g_quark_from_static_string ("drawing"));
+
+  dialog->collate_paper_node = gtk_css_node_new();
+  gtk_css_node_set_name (dialog->collate_paper_node, g_quark_from_static_string ("paper"));
+  gtk_css_node_set_parent (dialog->collate_paper_node,
+                           gtk_widget_get_css_node (dialog->collate_image));
+  g_object_unref (dialog->collate_paper_node);
+
+  dialog->page_layout_paper_node = gtk_css_node_new();
+  gtk_css_node_set_name (dialog->page_layout_paper_node, g_quark_from_static_string ("paper"));
+  gtk_css_node_set_parent (dialog->page_layout_paper_node,
+                           gtk_widget_get_css_node (dialog->page_layout_preview));
+  g_object_unref (dialog->page_layout_paper_node);
+}
+
+static void
+gtk_print_unix_dialog_constructed (GObject *object)
+{
+  gboolean use_header;
+
+  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->constructed (object);
+
+  g_object_get (object, "use-header-bar", &use_header, NULL);
+  if (use_header)
+    {
+       /* Reorder the preview button */
+       GtkWidget *button, *parent;
+       button = gtk_dialog_get_widget_for_response (GTK_DIALOG (object), GTK_RESPONSE_APPLY);
+       g_object_ref (button);
+       parent = gtk_widget_get_ancestor (button, GTK_TYPE_HEADER_BAR);
+       gtk_box_remove (GTK_BOX (gtk_widget_get_parent (button)), button);
+       gtk_header_bar_pack_end (GTK_HEADER_BAR (parent), button);
+       g_object_unref (button);
+    }
+
+  update_dialog_from_capabilities (GTK_PRINT_UNIX_DIALOG (object));
+}
+
+static void
+gtk_print_unix_dialog_dispose (GObject *object)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+  /* Make sure we don't destroy custom widgets owned by the backends */
+  clear_per_printer_ui (dialog);
+
+  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->dispose (object);
+}
+
+static void
+disconnect_printer_details_request (GtkPrintUnixDialog *dialog,
+                                    gboolean            details_failed)
+{
+  if (dialog->request_details_tag)
+    {
+      g_signal_handler_disconnect (dialog->request_details_printer,
+                                   dialog->request_details_tag);
+      dialog->request_details_tag = 0;
+      set_busy_cursor (dialog, FALSE);
+      if (details_failed)
+        gtk_printer_set_state_message (dialog->request_details_printer, _("Getting printer information failed"));
+      g_clear_object (&dialog->request_details_printer);
+    }
+}
+
+static void
+gtk_print_unix_dialog_finalize (GObject *object)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+  GList *iter;
+
+  unschedule_idle_mark_conflicts (dialog);
+  disconnect_printer_details_request (dialog, FALSE);
+
+  g_clear_object (&dialog->current_printer);
+  g_clear_object (&dialog->options);
+
+  if (dialog->number_up_layout_2_option)
+    {
+      dialog->number_up_layout_2_option->choices[0] = NULL;
+      dialog->number_up_layout_2_option->choices[1] = NULL;
+      g_free (dialog->number_up_layout_2_option->choices_display[0]);
+      g_free (dialog->number_up_layout_2_option->choices_display[1]);
+      dialog->number_up_layout_2_option->choices_display[0] = NULL;
+      dialog->number_up_layout_2_option->choices_display[1] = NULL;
+      g_object_unref (dialog->number_up_layout_2_option);
+      dialog->number_up_layout_2_option = NULL;
+    }
+
+  g_clear_object (&dialog->number_up_layout_n_option);
+  g_clear_object (&dialog->page_setup);
+  g_clear_object (&dialog->initial_settings);
+  g_clear_pointer (&dialog->waiting_for_printer, (GDestroyNotify)g_free);
+  g_clear_pointer (&dialog->format_for_printer, (GDestroyNotify)g_free);
+
+  for (iter = dialog->print_backends; iter != NULL; iter = iter->next)
+    gtk_print_backend_destroy (GTK_PRINT_BACKEND (iter->data));
+  g_list_free_full (dialog->print_backends, g_object_unref);
+  dialog->print_backends = NULL;
+
+  g_clear_object (&dialog->page_setup_list);
+  g_clear_object (&dialog->custom_paper_list);
+  g_clear_object (&dialog->manage_papers_list);
+
+  G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
+}
+
+static void
+gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
+}
+
+static GObject *
+gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
+                                                    GtkBuilder   *builder,
+                                                    const char   *childname)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (buildable);
+
+  if (strcmp (childname, "notebook") == 0)
+    return G_OBJECT (dialog->notebook);
+
+  return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+static void
+printer_status_cb (GtkPrintBackend    *backend,
+                   GtkPrinter         *printer,
+                   GtkPrintUnixDialog *dialog)
+{
+  GListModel *model;
+
+  /* When the pause state change then we need to update sensitive property
+   * of GTK_RESPONSE_OK button inside of selected_printer_changed function.
+   */
+  selected_printer_changed (dialog);
+
+  model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+
+  if (gtk_print_backend_printer_list_is_done (backend) &&
+      gtk_printer_is_default (printer) &&
+      gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
+    set_active_printer (dialog, gtk_printer_get_name (printer));
+}
+
+static void
+printer_added_cb (GListModel         *model,
+                  guint               position,
+                  guint               removed,
+                  guint               added,
+                  GtkPrintUnixDialog *dialog)
+{
+  guint i;
+
+  for (i = position; i < position + added; i++)
+    {
+      GtkPrinter *printer = g_list_model_get_item (model, i);
+
+      if (dialog->waiting_for_printer != NULL &&
+          strcmp (gtk_printer_get_name (printer), dialog->waiting_for_printer) == 0)
+        {
+          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+          g_free (dialog->waiting_for_printer);
+          dialog->waiting_for_printer = NULL;
+          g_object_unref (printer);
+          return;
+        }
+      else if (is_default_printer (dialog, printer) &&
+               gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (model)) == GTK_INVALID_LIST_POSITION)
+        {
+          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+          g_object_unref (printer);
+          return;
+        }
+
+      g_object_unref (printer);
+    }
+}
+
+static GListModel *
+load_print_backends (GtkPrintUnixDialog *dialog)
+{
+  GList *node;
+  GListStore *lists;
+
+  lists = g_list_store_new (G_TYPE_LIST_MODEL);
+
+  if (g_module_supported ())
+    dialog->print_backends = gtk_print_backend_load_modules ();
+
+  for (node = dialog->print_backends; node != NULL; node = node->next)
+    {
+      GtkPrintBackend *backend = node->data;
+
+      g_signal_connect_object (backend, "printer-status-changed",
+                               G_CALLBACK (printer_status_cb), G_OBJECT (dialog), 0);
+      g_list_store_append (lists, gtk_print_backend_get_printers (backend));
+    }
+
+  return G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (lists)));
+}
+
+static void
+gtk_print_unix_dialog_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+  switch (prop_id)
+    {
+    case PROP_PAGE_SETUP:
+      gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
+      break;
+    case PROP_CURRENT_PAGE:
+      gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
+      break;
+    case PROP_PRINT_SETTINGS:
+      gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
+      break;
+    case PROP_MANUAL_CAPABILITIES:
+      gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value));
+      break;
+    case PROP_SUPPORT_SELECTION:
+      gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value));
+      break;
+    case PROP_HAS_SELECTION:
+      gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value));
+      break;
+    case PROP_EMBED_PAGE_SETUP:
+      gtk_print_unix_dialog_set_embed_page_setup (dialog, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_print_unix_dialog_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
+
+  switch (prop_id)
+    {
+    case PROP_PAGE_SETUP:
+      g_value_set_object (value, dialog->page_setup);
+      break;
+    case PROP_CURRENT_PAGE:
+      g_value_set_int (value, dialog->current_page);
+      break;
+    case PROP_PRINT_SETTINGS:
+      g_value_take_object (value, gtk_print_unix_dialog_get_settings (dialog));
+      break;
+    case PROP_SELECTED_PRINTER:
+      g_value_set_object (value, dialog->current_printer);
+      break;
+    case PROP_MANUAL_CAPABILITIES:
+      g_value_set_flags (value, dialog->manual_capabilities);
+      break;
+    case PROP_SUPPORT_SELECTION:
+      g_value_set_boolean (value, dialog->support_selection);
+      break;
+    case PROP_HAS_SELECTION:
+      g_value_set_boolean (value, dialog->has_selection);
+      break;
+    case PROP_EMBED_PAGE_SETUP:
+      g_value_set_boolean (value, dialog->embed_page_setup);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static gboolean
+is_printer_active (gpointer item, gpointer data)
+{
+  GtkPrinter *printer = item;
+  GtkPrintUnixDialog *dialog = data;
+  gboolean result;
+
+  result = gtk_printer_is_active (printer);
+
+  if (result &&
+      dialog->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
+                                   GTK_PRINT_CAPABILITY_GENERATE_PS))
+    {
+       /* Check that the printer can handle at least one of the data
+        * formats that the application supports.
+        */
+       result = ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
+                 gtk_printer_accepts_pdf (printer)) ||
+                ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
+                 gtk_printer_accepts_ps (printer));
+    }
+
+  return result;
+}
+
+static int
+default_printer_list_sort_func (gconstpointer a,
+                                gconstpointer b,
+                                gpointer      user_data)
+{
+  GtkPrinter *a_printer = (gpointer)a;
+  GtkPrinter *b_printer = (gpointer)b;
+  const char *a_name;
+  const char *b_name;
+
+  if (a_printer == NULL && b_printer == NULL)
+    return 0;
+  else if (a_printer == NULL)
+   return 1;
+  else if (b_printer == NULL)
+   return -1;
+
+  if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
+    return 0;
+  else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
+    return -1;
+  else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
+    return 1;
+
+  a_name = gtk_printer_get_name (a_printer);
+  b_name = gtk_printer_get_name (b_printer);
+
+  if (a_name == NULL && b_name == NULL)
+    return  0;
+  else if (a_name == NULL && b_name != NULL)
+    return  1;
+  else if (a_name != NULL && b_name == NULL)
+    return -1;
+
+  return g_ascii_strcasecmp (a_name, b_name);
+}
+
+static GtkWidget *
+wrap_in_frame (const char *label,
+               GtkWidget   *child)
+{
+  GtkWidget *box, *label_widget;
+  char *bold_text;
+
+  label_widget = gtk_label_new (NULL);
+  gtk_widget_set_halign (label_widget, GTK_ALIGN_START);
+  gtk_widget_set_valign (label_widget, GTK_ALIGN_CENTER);
+
+  bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
+  gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
+  g_free (bold_text);
+
+  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_append (GTK_BOX (box), label_widget);
+
+  gtk_widget_set_margin_start (child, 12);
+  gtk_widget_set_halign (child, GTK_ALIGN_FILL);
+  gtk_widget_set_valign (child, GTK_ALIGN_FILL);
+
+  gtk_box_append (GTK_BOX (box), child);
+
+  return box;
+}
+
+static gboolean
+setup_option (GtkPrintUnixDialog     *dialog,
+              const char             *option_name,
+              GtkPrinterOptionWidget *widget)
+{
+  GtkPrinterOption *option;
+
+  option = gtk_printer_option_set_lookup (dialog->options, option_name);
+  gtk_printer_option_widget_set_source (widget, option);
+
+  return option != NULL;
+}
+
+static void
+add_option_to_extension_point (GtkPrinterOption *option,
+                               gpointer          data)
+{
+  GtkWidget *extension_point = data;
+  GtkWidget *widget;
+
+  widget = gtk_printer_option_widget_new (option);
+
+  if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
+    {
+      GtkWidget *label, *hbox;
+
+      gtk_widget_set_valign (widget, GTK_ALIGN_BASELINE_FILL);
+
+      label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
+      gtk_widget_set_visible (label, TRUE);
+      gtk_widget_set_halign (label, GTK_ALIGN_START);
+      gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+
+      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+      gtk_widget_set_valign (hbox, GTK_ALIGN_BASELINE_FILL);
+      gtk_box_append (GTK_BOX (hbox), label);
+      gtk_box_append (GTK_BOX (hbox), widget);
+
+      gtk_box_append (GTK_BOX (extension_point), hbox);
+    }
+  else
+    gtk_box_append (GTK_BOX (extension_point), widget);
+}
+
+static int
+grid_rows (GtkGrid *table)
+{
+  int t0, t1, l, t, w, h;
+  GtkWidget *c;
+  gboolean first;
+
+  t0 = t1 = 0;
+  for (c = gtk_widget_get_first_child (GTK_WIDGET (table)), first = TRUE;
+       c != NULL;
+       c  = gtk_widget_get_next_sibling (GTK_WIDGET (c)), first = FALSE)
+    {
+      gtk_grid_query_child (table, c, &l, &t, &w, &h);
+      if (first)
+        {
+          t0 = t;
+          t1 = t + h;
+        }
+      else
+        {
+          if (t < t0)
+            t0 = t;
+          if (t + h > t1)
+            t1 = t + h;
+        }
+    }
+
+  return t1 - t0;
+}
+
+static void
+add_option_to_table (GtkPrinterOption *option,
+                     gpointer          user_data)
+{
+  GtkGrid *table;
+  GtkWidget *label, *widget;
+  guint row;
+
+  table = GTK_GRID (user_data);
+
+  if (g_str_has_prefix (option->name, "gtk-"))
+    return;
+
+  row = grid_rows (table);
+
+  widget = gtk_printer_option_widget_new (option);
+
+  if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
+    {
+      label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
+      gtk_widget_set_visible (label, TRUE);
+
+      gtk_widget_set_halign (label, GTK_ALIGN_START);
+      gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+
+      gtk_grid_attach (table, label, 0, row - 1, 1, 1);
+      gtk_grid_attach (table, widget, 1, row - 1, 1, 1);
+    }
+  else
+    gtk_grid_attach (table, widget, 0, row - 1, 2, 1);
+}
+
+static void
+setup_page_table (GtkPrinterOptionSet *options,
+                  const char          *group,
+                  GtkWidget           *table,
+                  GtkWidget           *page)
+{
+  int nrows;
+
+  gtk_printer_option_set_foreach_in_group (options, group,
+                                           add_option_to_table,
+                                           table);
+
+  nrows = grid_rows (GTK_GRID (table));
+  gtk_widget_set_visible (page, nrows > 0);
+}
+
+static void
+update_print_at_option (GtkPrintUnixDialog *dialog)
+{
+  GtkPrinterOption *option;
+
+  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
+
+  if (option == NULL)
+    return;
+
+  if (dialog->updating_print_at)
+    return;
+
+  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_at_radio)))
+    gtk_printer_option_set (option, "at");
+  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_hold_radio)))
+    gtk_printer_option_set (option, "on-hold");
+  else
+    gtk_printer_option_set (option, "now");
+
+  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
+  if (option != NULL)
+    {
+      const char *text;
+
+      text = gtk_editable_get_text (GTK_EDITABLE (dialog->print_at_entry));
+      gtk_printer_option_set (option, text);
+    }
+}
+
+
+static gboolean
+setup_print_at (GtkPrintUnixDialog *dialog)
+{
+  GtkPrinterOption *option;
+
+  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time");
+
+  if (option == NULL)
+    {
+      gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
+      gtk_widget_set_sensitive (dialog->print_at_radio, FALSE);
+      gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
+      gtk_widget_set_sensitive (dialog->print_hold_radio, FALSE);
+      gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), "");
+      return FALSE;
+    }
+
+  dialog->updating_print_at = TRUE;
+
+  gtk_widget_set_sensitive (dialog->print_at_entry, FALSE);
+  gtk_widget_set_sensitive (dialog->print_at_radio,
+                            gtk_printer_option_has_choice (option, "at"));
+
+  gtk_widget_set_sensitive (dialog->print_hold_radio,
+                            gtk_printer_option_has_choice (option, "on-hold"));
+
+  update_print_at_option (dialog);
+
+  if (strcmp (option->value, "at") == 0)
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_at_radio), TRUE);
+  else if (strcmp (option->value, "on-hold") == 0)
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_hold_radio), TRUE);
+  else
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
+
+  option = gtk_printer_option_set_lookup (dialog->options, "gtk-print-time-text");
+  if (option != NULL)
+    gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), option->value);
+
+  dialog->updating_print_at = FALSE;
+
+  return TRUE;
+}
+
+static void
+update_dialog_from_settings (GtkPrintUnixDialog *dialog)
+{
+  GList *groups, *l;
+  char *group;
+  GtkWidget *table, *frame;
+  gboolean has_advanced, has_job;
+  guint nrows;
+  GtkWidget *child;
+
+  if (dialog->current_printer == NULL)
+    {
+       clear_per_printer_ui (dialog);
+       gtk_widget_set_visible (dialog->job_page, FALSE);
+       gtk_widget_set_visible (dialog->advanced_page, FALSE);
+       gtk_widget_set_visible (dialog->image_quality_page, FALSE);
+       gtk_widget_set_visible (dialog->finishing_page, FALSE);
+       gtk_widget_set_visible (dialog->color_page, FALSE);
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+
+       return;
+    }
+
+  setup_option (dialog, "gtk-n-up", dialog->pages_per_sheet);
+  setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
+  setup_option (dialog, "gtk-duplex", dialog->duplex);
+  setup_option (dialog, "gtk-paper-type", dialog->paper_type);
+  setup_option (dialog, "gtk-paper-source", dialog->paper_source);
+  setup_option (dialog, "gtk-output-tray", dialog->output_tray);
+
+  has_job = FALSE;
+  has_job |= setup_option (dialog, "gtk-job-prio", dialog->job_prio);
+  has_job |= setup_option (dialog, "gtk-billing-info", dialog->billing_info);
+  has_job |= setup_option (dialog, "gtk-cover-before", dialog->cover_before);
+  has_job |= setup_option (dialog, "gtk-cover-after", dialog->cover_after);
+  has_job |= setup_print_at (dialog);
+
+  gtk_widget_set_visible (dialog->job_page, has_job);
+
+  setup_page_table (dialog->options,
+                    "ImageQualityPage",
+                    dialog->image_quality_table,
+                    dialog->image_quality_page);
+
+  setup_page_table (dialog->options,
+                    "FinishingPage",
+                    dialog->finishing_table,
+                    dialog->finishing_page);
+
+  setup_page_table (dialog->options,
+                    "ColorPage",
+                    dialog->color_table,
+                    dialog->color_page);
+
+  gtk_printer_option_set_foreach_in_group (dialog->options,
+                                           "GtkPrintDialogExtension",
+                                           add_option_to_extension_point,
+                                           dialog->extension_point);
+
+  /* A bit of a hack, keep the last option flush right.
+   * This keeps the file format radios from moving as the
+   * filename changes.
+   */
+  child = gtk_widget_get_last_child (dialog->extension_point);
+  if (child && child != gtk_widget_get_first_child (dialog->extension_point))
+    gtk_widget_set_halign (child, GTK_ALIGN_END);
+
+  /* Put the rest of the groups in the advanced page */
+  groups = gtk_printer_option_set_get_groups (dialog->options);
+
+  has_advanced = FALSE;
+  for (l = groups; l != NULL; l = l->next)
+    {
+      group = l->data;
+
+      if (group == NULL)
+        continue;
+
+      if (strcmp (group, "ImageQualityPage") == 0 ||
+          strcmp (group, "ColorPage") == 0 ||
+          strcmp (group, "FinishingPage") == 0 ||
+          strcmp (group, "GtkPrintDialogExtension") == 0)
+        continue;
+
+      table = gtk_grid_new ();
+      gtk_grid_set_row_spacing (GTK_GRID (table), 6);
+      gtk_grid_set_column_spacing (GTK_GRID (table), 12);
+
+      gtk_printer_option_set_foreach_in_group (dialog->options,
+                                               group,
+                                               add_option_to_table,
+                                               table);
+
+      nrows = grid_rows (GTK_GRID (table));
+      if (nrows == 0)
+        {
+          g_object_unref (g_object_ref_sink (table));
+        }
+      else
+        {
+          has_advanced = TRUE;
+          frame = wrap_in_frame (group, table);
+          gtk_box_append (GTK_BOX (dialog->advanced_vbox), frame);
+        }
+    }
+
+  gtk_widget_set_visible (dialog->advanced_page, has_advanced);
+
+  g_list_free_full (groups, g_free);
+}
+
+static void
+update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
+{
+  GtkPrintCapabilities caps;
+  gboolean can_collate;
+  const char *copies;
+  GtkWidget *button;
+
+  copies = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
+  can_collate = (*copies != '\0' && atoi (copies) > 1);
+
+  caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+  gtk_widget_set_sensitive (dialog->page_set_combo,
+                            caps & GTK_PRINT_CAPABILITY_PAGE_SET);
+  gtk_widget_set_sensitive (dialog->copies_spin,
+                            caps & GTK_PRINT_CAPABILITY_COPIES);
+  gtk_widget_set_sensitive (dialog->collate_check,
+                            can_collate &&
+                            (caps & GTK_PRINT_CAPABILITY_COLLATE));
+  gtk_widget_set_sensitive (dialog->reverse_check,
+                            caps & GTK_PRINT_CAPABILITY_REVERSE);
+  gtk_widget_set_sensitive (dialog->scale_spin,
+                            caps & GTK_PRINT_CAPABILITY_SCALE);
+  gtk_widget_set_sensitive (GTK_WIDGET (dialog->pages_per_sheet),
+                            caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
+
+  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
+  gtk_widget_set_visible (button, (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0);
+
+  update_collate_icon (NULL, dialog);
+}
+
+static gboolean
+page_setup_is_equal (GtkPageSetup *a,
+                     GtkPageSetup *b)
+{
+  return
+    gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+                             gtk_page_setup_get_paper_size (b)) &&
+    gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
+    gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
+}
+
+static gboolean
+page_setup_is_same_size (GtkPageSetup *a,
+                         GtkPageSetup *b)
+{
+  return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
+                                  gtk_page_setup_get_paper_size (b));
+}
+
+static gboolean
+set_paper_size (GtkPrintUnixDialog *dialog,
+                GtkPageSetup       *page_setup,
+                gboolean            size_only,
+                gboolean            add_item)
+{
+  GListModel *model;
+  GtkPageSetup *list_page_setup;
+  guint i;
+
+  if (!dialog->internal_page_setup_change)
+    return TRUE;
+
+  if (page_setup == NULL)
+    return FALSE;
+
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+  for (i = 0; i < g_list_model_get_n_items (model); i++)
+    {
+      list_page_setup = g_list_model_get_item (model, i);
+      if (list_page_setup == NULL)
+        continue;
+
+      if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
+          (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
+        {
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
+                                      gtk_page_setup_get_orientation (page_setup));
+          g_object_unref (list_page_setup);
+          return TRUE;
+        }
+
+      g_object_unref (list_page_setup);
+    }
+
+  if (add_item)
+    {
+      i = g_list_model_get_n_items (model);
+      g_list_store_append (dialog->page_setup_list, page_setup);
+      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->paper_size_combo), i);
+      gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->orientation_combo),
+                                  gtk_page_setup_get_orientation (page_setup));
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
+{
+  g_list_store_remove_all (dialog->custom_paper_list);
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+}
+
+static void
+fill_paper_sizes (GtkPrintUnixDialog *dialog,
+                  GtkPrinter         *printer)
+{
+  GList *list, *l;
+  GtkPageSetup *page_setup;
+  GtkPaperSize *paper_size;
+  int i;
+
+  g_list_store_remove_all (dialog->page_setup_list);
+
+  if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
+    {
+      for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
+        {
+          page_setup = gtk_page_setup_new ();
+          paper_size = gtk_paper_size_new (common_paper_sizes[i]);
+          gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
+          gtk_paper_size_free (paper_size);
+          g_list_store_append (dialog->page_setup_list, page_setup);
+          g_object_unref (page_setup);
+        }
+    }
+  else
+    {
+      for (l = list; l != NULL; l = l->next)
+        {
+          page_setup = l->data;
+          g_list_store_append (dialog->page_setup_list, page_setup);
+          g_object_unref (page_setup);
+        }
+      g_list_free (list);
+    }
+}
+
+static void
+update_paper_sizes (GtkPrintUnixDialog *dialog)
+{
+  GtkPageSetup *current_page_setup = NULL;
+  GtkPrinter   *printer;
+
+  printer = gtk_print_unix_dialog_get_selected_printer (dialog);
+
+  fill_paper_sizes (dialog, printer);
+  fill_custom_paper_sizes (dialog);
+
+  current_page_setup = gtk_page_setup_copy (gtk_print_unix_dialog_get_page_setup (dialog));
+
+  if (current_page_setup)
+    {
+      if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
+        set_paper_size (dialog, current_page_setup, TRUE, TRUE);
+
+      g_object_unref (current_page_setup);
+    }
+}
+
+static void
+mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+  GtkPrinter *printer;
+  gboolean have_conflict;
+
+  have_conflict = FALSE;
+
+  printer = dialog->current_printer;
+
+  if (printer)
+    {
+      g_signal_handler_block (dialog->options, dialog->options_changed_handler);
+
+      gtk_printer_option_set_clear_conflicts (dialog->options);
+      have_conflict = _gtk_printer_mark_conflicts (printer, dialog->options);
+
+      g_signal_handler_unblock (dialog->options, dialog->options_changed_handler);
+    }
+
+  gtk_widget_set_visible (dialog->conflicts_widget, have_conflict);
+}
+
+static gboolean
+mark_conflicts_callback (gpointer data)
+{
+  GtkPrintUnixDialog *dialog = data;
+
+  dialog->mark_conflicts_id = 0;
+
+  mark_conflicts (dialog);
+
+  return FALSE;
+}
+
+static void
+unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+  if (dialog->mark_conflicts_id != 0)
+    {
+      g_source_remove (dialog->mark_conflicts_id);
+      dialog->mark_conflicts_id = 0;
+    }
+}
+
+static void
+schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
+{
+  if (dialog->mark_conflicts_id != 0)
+    return;
+
+  dialog->mark_conflicts_id = g_idle_add (mark_conflicts_callback, dialog);
+  gdk_source_set_static_name_by_id (dialog->mark_conflicts_id, "[gtk] mark_conflicts_callback");
+}
+
+static void
+options_changed_cb (GtkPrintUnixDialog *dialog)
+{
+  schedule_idle_mark_conflicts (dialog);
+
+  g_free (dialog->waiting_for_printer);
+  dialog->waiting_for_printer = NULL;
+}
+
+static void
+clear_per_printer_ui (GtkPrintUnixDialog *dialog)
+{
+  GtkWidget *child;
+
+  if (dialog->finishing_table == NULL)
+    return;
+
+  while ((child = gtk_widget_get_first_child (dialog->finishing_table)))
+    gtk_grid_remove (GTK_GRID (dialog->finishing_table), child);
+  while ((child = gtk_widget_get_first_child (dialog->image_quality_table)))
+    gtk_grid_remove (GTK_GRID (dialog->image_quality_table), child);
+  while ((child = gtk_widget_get_first_child (dialog->color_table)))
+    gtk_grid_remove (GTK_GRID (dialog->color_table), child);
+  while ((child = gtk_widget_get_first_child (dialog->advanced_vbox)))
+    gtk_box_remove (GTK_BOX (dialog->advanced_vbox), child);
+  while ((child = gtk_widget_get_first_child (dialog->extension_point)))
+    gtk_box_remove (GTK_BOX (dialog->extension_point), child);
+}
+
+static void
+printer_details_acquired (GtkPrinter         *printer,
+                          gboolean            success,
+                          GtkPrintUnixDialog *dialog)
+{
+  disconnect_printer_details_request (dialog, !success);
+
+  if (success)
+    selected_printer_changed (dialog);
+}
+
+static void
+selected_printer_changed (GtkPrintUnixDialog *dialog)
+{
+  GListModel *model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+  GtkPrinter *printer;
+
+  /* Whenever the user selects a printer we stop looking for
+   * the printer specified in the initial settings
+   */
+  if (dialog->waiting_for_printer &&
+      !dialog->internal_printer_change)
+    {
+      g_free (dialog->waiting_for_printer);
+      dialog->waiting_for_printer = NULL;
+    }
+
+  disconnect_printer_details_request (dialog, FALSE);
+
+  printer = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model));
+
+  /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
+   * accepts/rejects jobs
+   */
+  if (printer != NULL)
+    {
+      if (!gtk_printer_is_accepting_jobs (printer))
+        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+      else if (dialog->current_printer == printer && gtk_printer_has_details (printer))
+        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
+    }
+
+  if (printer != NULL && !gtk_printer_has_details (printer))
+    {
+      gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+      dialog->request_details_tag = g_signal_connect (printer, "details-acquired",
+                                                      G_CALLBACK (printer_details_acquired), dialog);
+
+      dialog->request_details_printer = g_object_ref (printer);
+      set_busy_cursor (dialog, TRUE);
+      gtk_printer_set_state_message (printer, _("Getting printer information…"));
+      gtk_printer_request_details (printer);
+      return;
+    }
+
+  if (printer == dialog->current_printer)
+    return;
+
+  if (dialog->options)
+    {
+      g_clear_object (&dialog->options);
+      clear_per_printer_ui (dialog);
+    }
+
+  g_clear_object (&dialog->current_printer);
+  dialog->printer_capabilities = 0;
+
+  if (printer != NULL && gtk_printer_is_accepting_jobs (printer))
+    gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
+  dialog->current_printer = g_object_ref (printer);
+
+  if (printer != NULL)
+    {
+      if (!dialog->page_setup_set)
+        {
+          /* if no explicit page setup has been set, use the printer default */
+          GtkPageSetup *page_setup;
+
+          page_setup = gtk_printer_get_default_page_size (printer);
+
+          if (!page_setup)
+            page_setup = gtk_page_setup_new ();
+
+          if (page_setup && dialog->page_setup)
+            gtk_page_setup_set_orientation (page_setup, gtk_page_setup_get_orientation (dialog->page_setup));
+
+          g_clear_object (&dialog->page_setup);
+          dialog->page_setup = page_setup; /* transfer ownership */
+        }
+
+      dialog->printer_capabilities = gtk_printer_get_capabilities (printer);
+      dialog->options = _gtk_printer_get_options (printer,
+                                                dialog->initial_settings,
+                                                dialog->page_setup,
+                                                dialog->manual_capabilities);
+
+      dialog->options_changed_handler =
+        g_signal_connect_swapped (dialog->options, "changed", G_CALLBACK (options_changed_cb), dialog);
+      schedule_idle_mark_conflicts (dialog);
+    }
+
+  update_dialog_from_settings (dialog);
+  update_dialog_from_capabilities (dialog);
+
+  dialog->internal_page_setup_change = TRUE;
+  update_paper_sizes (dialog);
+  dialog->internal_page_setup_change = FALSE;
+
+  g_object_notify (G_OBJECT (dialog), "selected-printer");
+}
+
+static void
+update_collate_icon (GtkToggleButton    *toggle_button,
+                     GtkPrintUnixDialog *dialog)
+{
+  gtk_widget_queue_draw (dialog->collate_image);
+}
+
+static void
+paint_page (GtkPrintUnixDialog *dialog,
+            GtkWidget  *widget,
+            cairo_t    *cr,
+            int         x,
+            int         y,
+            const char *text,
+            int         text_x)
+{
+  GtkCssStyle *style;
+  int width, height;
+  int text_y;
+  GdkRGBA color;
+  GtkSnapshot *snapshot;
+  GskRenderNode *node;
+  GtkCssBoxes boxes;
+
+  width = 20;
+  height = 26;
+  text_y = 21;
+
+  style = gtk_css_node_get_style (dialog->collate_paper_node);
+
+  snapshot = gtk_snapshot_new ();
+  gtk_css_boxes_init_border_box (&boxes, style, x, y, width, height);
+  gtk_css_style_snapshot_background (&boxes, snapshot);
+  gtk_css_style_snapshot_border (&boxes, snapshot);
+
+  node = gtk_snapshot_free_to_node (snapshot);
+  if (node)
+    {
+      gsk_render_node_draw (node, cr);
+      gsk_render_node_unref (node);
+    }
+
+  color = *gtk_css_color_value_get_rgba (style->core->color);
+  gdk_cairo_set_source_rgba (cr, &color);
+
+  cairo_select_font_face (cr, "Sans",
+                          CAIRO_FONT_SLANT_NORMAL,
+                          CAIRO_FONT_WEIGHT_NORMAL);
+  cairo_set_font_size (cr, 9);
+  cairo_move_to (cr, x + text_x, y + text_y);
+  cairo_show_text (cr, text);
+}
+
+static void
+draw_collate (GtkDrawingArea *da,
+              cairo_t        *cr,
+              int             width,
+              int             height,
+              gpointer        data)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
+  GtkWidget *widget = GTK_WIDGET (da);
+  gboolean collate, reverse, rtl;
+  int copies;
+  int text_x;
+  int x, y, x1, x2, p1, p2;
+
+  collate = dialog_get_collate (dialog);
+  reverse = dialog_get_reverse (dialog);
+  copies = dialog_get_n_copies (dialog);
+
+  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
+
+  x = (width - 30) / 2;
+  y = (height - 36) / 2;
+  if (rtl)
+    {
+      x1 = x;
+      x2 = x - 36;
+      p1 = 0;
+      p2 = 10;
+      text_x = 4;
+    }
+  else
+    {
+      x1 = x;
+      x2 = x + 36;
+      p1 = 10;
+      p2 = 0;
+      text_x = 11;
+    }
+
+  if (copies == 1)
+    {
+      paint_page (dialog, widget, cr, x1 + p1, y, reverse ? "1" : "2", text_x);
+      paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
+    }
+  else
+    {
+      paint_page (dialog, widget, cr, x1 + p1, y, collate == reverse ? "1" : "2", text_x);
+      paint_page (dialog, widget, cr, x1 + p2, y + 10, reverse ? "2" : "1", text_x);
+
+      paint_page (dialog, widget, cr, x2 + p1, y, reverse ? "1" : "2", text_x);
+      paint_page (dialog, widget, cr, x2 + p2, y + 10, collate == reverse ? "2" : "1", text_x);
+    }
+}
+
+static gboolean
+page_range_entry_focus_changed (GtkWidget          *entry,
+                                GParamSpec         *pspec,
+                                GtkPrintUnixDialog *dialog)
+{
+  if (gtk_widget_has_focus (entry))
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
+
+  return FALSE;
+}
+
+static void
+update_page_range_entry_sensitivity (GtkWidget *button,
+                                    GtkPrintUnixDialog *dialog)
+{
+  gboolean active;
+
+  active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
+
+  if (active)
+    gtk_widget_grab_focus (dialog->page_range_entry);
+}
+
+static void
+update_print_at_entry_sensitivity (GtkWidget *button,
+                                  GtkPrintUnixDialog *dialog)
+{
+  gboolean active;
+
+  active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
+
+  gtk_widget_set_sensitive (dialog->print_at_entry, active);
+
+  if (active)
+    gtk_widget_grab_focus (dialog->print_at_entry);
+}
+
+static gboolean
+is_range_separator (char c)
+{
+  return (c == ',' || c == ';' || c == ':');
+}
+
+static GtkPageRange *
+dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
+                        int                *n_ranges_out)
+{
+  int i, n_ranges;
+  const char *text, *p;
+  char *next;
+  GtkPageRange *ranges;
+  int start, end;
+
+  text = gtk_editable_get_text (GTK_EDITABLE (dialog->page_range_entry));
+
+  if (*text == 0)
+    {
+      *n_ranges_out = 0;
+      return NULL;
+    }
+
+  n_ranges = 1;
+  p = text;
+  while (*p)
+    {
+      if (is_range_separator (*p))
+        n_ranges++;
+      p++;
+    }
+
+  ranges = g_new0 (GtkPageRange, n_ranges);
+
+  i = 0;
+  p = text;
+  while (*p)
+    {
+      while (isspace (*p)) p++;
+
+      if (*p == '-')
+        {
+          /* a half-open range like -2 */
+          start = 1;
+        }
+      else
+        {
+          start = (int)strtol (p, &next, 10);
+          if (start < 1)
+            start = 1;
+          p = next;
+        }
+
+      end = start;
+
+      while (isspace (*p)) p++;
+
+      if (*p == '-')
+        {
+          p++;
+          end = (int)strtol (p, &next, 10);
+          if (next == p) /* a half-open range like 2- */
+            end = 0;
+          else if (end < start)
+            end = start;
+        }
+
+      ranges[i].start = start - 1;
+      ranges[i].end = end - 1;
+      i++;
+
+      /* Skip until end or separator */
+      while (*p && !is_range_separator (*p))
+        p++;
+
+      /* if not at end, skip separator */
+      if (*p)
+        p++;
+    }
+
+  *n_ranges_out = i;
+
+  return ranges;
+}
+
+static void
+dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
+                        GtkPageRange       *ranges,
+                        int                 n_ranges)
+{
+  int i;
+  GString *s = g_string_new (NULL);
+
+  for (i = 0; i < n_ranges; i++)
+    {
+      g_string_append_printf (s, "%d", ranges[i].start + 1);
+      if (ranges[i].end > ranges[i].start)
+        g_string_append_printf (s, "-%d", ranges[i].end + 1);
+      else if (ranges[i].end == -1)
+        g_string_append (s, "-");
+
+      if (i != n_ranges - 1)
+        g_string_append (s, ",");
+    }
+
+  gtk_editable_set_text (GTK_EDITABLE (dialog->page_range_entry), s->str);
+
+  g_string_free (s, TRUE);
+}
+
+static GtkPrintPages
+dialog_get_print_pages (GtkPrintUnixDialog *dialog)
+{
+  if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->all_pages_radio)))
+    return GTK_PRINT_PAGES_ALL;
+  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->current_page_radio)))
+    return GTK_PRINT_PAGES_CURRENT;
+  else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->selection_radio)))
+    return GTK_PRINT_PAGES_SELECTION;
+  else
+    return GTK_PRINT_PAGES_RANGES;
+}
+
+static void
+dialog_set_print_pages (GtkPrintUnixDialog *dialog,
+                        GtkPrintPages       pages)
+{
+  if (pages == GTK_PRINT_PAGES_RANGES)
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
+  else if (pages == GTK_PRINT_PAGES_CURRENT)
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->current_page_radio), TRUE);
+  else if (pages == GTK_PRINT_PAGES_SELECTION)
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->selection_radio), TRUE);
+  else
+    gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->all_pages_radio), TRUE);
+}
+
+static double
+dialog_get_scale (GtkPrintUnixDialog *dialog)
+{
+  if (gtk_widget_is_sensitive (dialog->scale_spin))
+    return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->scale_spin));
+  else
+    return 100.0;
+}
+
+static void
+dialog_set_scale (GtkPrintUnixDialog *dialog,
+                  double              val)
+{
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), val);
+}
+
+static GtkPageSet
+dialog_get_page_set (GtkPrintUnixDialog *dialog)
+{
+  if (gtk_widget_is_sensitive (dialog->page_set_combo))
+    return (GtkPageSet)gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->page_set_combo));
+  else
+    return GTK_PAGE_SET_ALL;
+}
+
+static void
+dialog_set_page_set (GtkPrintUnixDialog *dialog,
+                     GtkPageSet          val)
+{
+  gtk_drop_down_set_selected (GTK_DROP_DOWN (dialog->page_set_combo), (guint)val);
+}
+
+static int
+dialog_get_n_copies (GtkPrintUnixDialog *dialog)
+{
+  GtkAdjustment *adjustment;
+  const char *text;
+  char *endptr = NULL;
+  int n_copies;
+
+  adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (dialog->copies_spin));
+
+  text = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
+  n_copies = g_ascii_strtoull (text, &endptr, 0);
+
+  if (gtk_widget_is_sensitive (dialog->copies_spin))
+    {
+      if (n_copies != 0 && endptr != text && (endptr != NULL && endptr[0] == '\0') &&
+          n_copies >= gtk_adjustment_get_lower (adjustment) &&
+          n_copies <= gtk_adjustment_get_upper (adjustment))
+        {
+          return n_copies;
+        }
+
+      return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->copies_spin));
+    }
+
+  return 1;
+}
+
+static void
+dialog_set_n_copies (GtkPrintUnixDialog *dialog,
+                     int                 n_copies)
+{
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->copies_spin), n_copies);
+}
+
+static gboolean
+dialog_get_collate (GtkPrintUnixDialog *dialog)
+{
+  if (gtk_widget_is_sensitive (dialog->collate_check))
+    return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->collate_check));
+  return FALSE;
+}
+
+static void
+dialog_set_collate (GtkPrintUnixDialog *dialog,
+                    gboolean            collate)
+{
+  gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), collate);
+}
+
+static gboolean
+dialog_get_reverse (GtkPrintUnixDialog *dialog)
+{
+  if (gtk_widget_is_sensitive (dialog->reverse_check))
+    return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_check));
+  return FALSE;
+}
+
+static void
+dialog_set_reverse (GtkPrintUnixDialog *dialog,
+                    gboolean            reverse)
+{
+  gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), reverse);
+}
+
+static int
+dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
+{
+  const char *val;
+  int num;
+
+  val = gtk_printer_option_widget_get_value (dialog->pages_per_sheet);
+
+  num = 1;
+
+  if (val)
+    {
+      num = atoi(val);
+      if (num < 1)
+        num = 1;
+    }
+
+  return num;
+}
+
+static GtkNumberUpLayout
+dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
+{
+  GtkPrintCapabilities       caps;
+  GtkNumberUpLayout          layout;
+  const char                *val;
+  GEnumClass                *enum_class;
+  GEnumValue                *enum_value;
+
+  val = gtk_printer_option_widget_get_value (dialog->number_up_layout);
+
+  caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+  if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
+    return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+
+  if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
+    layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+  else
+    layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
+
+  if (val == NULL)
+    return layout;
+
+  if (val[0] == '\0' && dialog->options)
+    {
+      GtkPrinterOption *option = gtk_printer_option_set_lookup (dialog->options, "gtk-n-up-layout");
+      if (option)
+        val = option->value;
+    }
+
+  enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
+  enum_value = g_enum_get_value_by_nick (enum_class, val);
+  if (enum_value)
+    layout = enum_value->value;
+  g_type_class_unref (enum_class);
+
+  return layout;
+}
+
+static void
+draw_page (GtkDrawingArea *da,
+           cairo_t        *cr,
+           int             width,
+           int             height,
+           gpointer        data)
+{
+  GtkWidget *widget = GTK_WIDGET (da);
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
+  GtkCssStyle *style;
+  double ratio;
+  int w, h, tmp;
+  int pages_x, pages_y, i, x, y, layout_w, layout_h;
+  double page_width, page_height;
+  GtkPageOrientation orientation;
+  gboolean landscape;
+  PangoLayout *layout;
+  PangoFontDescription *font;
+  char *text;
+  GdkRGBA color;
+  GtkNumberUpLayout number_up_layout;
+  int start_x, end_x, start_y, end_y;
+  int dx, dy;
+  gboolean horizontal;
+  GtkPageSetup *page_setup;
+  double paper_width, paper_height;
+  double pos_x, pos_y;
+  int pages_per_sheet;
+  gboolean ltr = TRUE;
+  GtkSnapshot *snapshot;
+  GtkCssBoxes boxes;
+  GskRenderNode *node;
+
+  orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+  landscape =
+    (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
+    (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
+
+  number_up_layout = dialog_get_number_up_layout (dialog);
+
+  cairo_save (cr);
+
+  page_setup = gtk_print_unix_dialog_get_page_setup (dialog);
+
+  if (page_setup != NULL)
+    {
+      if (!landscape)
+        {
+          paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
+          paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
+        }
+      else
+        {
+          paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
+          paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
+        }
+
+      if (paper_width < paper_height)
+        {
+          h = EXAMPLE_PAGE_AREA_SIZE - 3;
+          w = (paper_height != 0) ? h * paper_width / paper_height : 0;
+        }
+      else
+        {
+          w = EXAMPLE_PAGE_AREA_SIZE - 3;
+          h = (paper_width != 0) ? w * paper_height / paper_width : 0;
+        }
+
+      if (paper_width == 0)
+        w = 0;
+
+      if (paper_height == 0)
+        h = 0;
+    }
+  else
+    {
+      ratio = G_SQRT2;
+      w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
+      h = EXAMPLE_PAGE_AREA_SIZE - 3;
+    }
+
+  pages_per_sheet = dialog_get_pages_per_sheet (dialog);
+  switch (pages_per_sheet)
+    {
+    default:
+    case 1:
+      pages_x = 1; pages_y = 1;
+      break;
+    case 2:
+      landscape = !landscape;
+      pages_x = 1; pages_y = 2;
+      break;
+    case 4:
+      pages_x = 2; pages_y = 2;
+      break;
+    case 6:
+      landscape = !landscape;
+      pages_x = 2; pages_y = 3;
+      break;
+    case 9:
+      pages_x = 3; pages_y = 3;
+      break;
+    case 16:
+      pages_x = 4; pages_y = 4;
+      break;
+    }
+
+  if (landscape)
+    {
+      tmp = w;
+      w = h;
+      h = tmp;
+
+      tmp = pages_x;
+      pages_x = pages_y;
+      pages_y = tmp;
+    }
+
+  style = gtk_css_node_get_style (dialog->page_layout_paper_node);
+  color = *gtk_css_color_value_get_rgba (style->core->color);
+
+  pos_x = (width - w) / 2;
+  pos_y = (height - h) / 2 - 10;
+  cairo_translate (cr, pos_x, pos_y);
+
+  snapshot = gtk_snapshot_new ();
+  gtk_css_boxes_init_border_box (&boxes, style, 1, 1, w, h);
+  gtk_css_style_snapshot_background (&boxes, snapshot);
+  gtk_css_style_snapshot_border (&boxes, snapshot);
+
+  node = gtk_snapshot_free_to_node (snapshot);
+  if (node)
+    {
+      gsk_render_node_draw (node, cr);
+      gsk_render_node_unref (node);
+    }
+
+  cairo_set_line_width (cr, 1.0);
+
+  i = 1;
+
+  page_width = (double)w / pages_x;
+  page_height = (double)h / pages_y;
+
+  layout  = pango_cairo_create_layout (cr);
+
+  font = pango_font_description_new ();
+  pango_font_description_set_family (font, "sans");
+
+  if (page_height > 0)
+    pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
+  else
+    pango_font_description_set_absolute_size (font, 1);
+
+  pango_layout_set_font_description (layout, font);
+  pango_font_description_free (font);
+
+  pango_layout_set_width (layout, page_width * PANGO_SCALE);
+  pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+
+  switch (number_up_layout)
+    {
+      default:
+      case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+        start_x = 0;
+        end_x = pages_x - 1;
+        start_y = 0;
+        end_y = pages_y - 1;
+        dx = 1;
+        dy = 1;
+        horizontal = TRUE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+        start_x = 0;
+        end_x = pages_x - 1;
+        start_y = pages_y - 1;
+        end_y = 0;
+        dx = 1;
+        dy = - 1;
+        horizontal = TRUE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+        start_x = pages_x - 1;
+        end_x = 0;
+        start_y = 0;
+        end_y = pages_y - 1;
+        dx = - 1;
+        dy = 1;
+        horizontal = TRUE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+        start_x = pages_x - 1;
+        end_x = 0;
+        start_y = pages_y - 1;
+        end_y = 0;
+        dx = - 1;
+        dy = - 1;
+        horizontal = TRUE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+        start_x = 0;
+        end_x = pages_x - 1;
+        start_y = 0;
+        end_y = pages_y - 1;
+        dx = 1;
+        dy = 1;
+        horizontal = FALSE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+        start_x = pages_x - 1;
+        end_x = 0;
+        start_y = 0;
+        end_y = pages_y - 1;
+        dx = - 1;
+        dy = 1;
+        horizontal = FALSE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+        start_x = 0;
+        end_x = pages_x - 1;
+        start_y = pages_y - 1;
+        end_y = 0;
+        dx = 1;
+        dy = - 1;
+        horizontal = FALSE;
+        break;
+      case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+        start_x = pages_x - 1;
+        end_x = 0;
+        start_y = pages_y - 1;
+        end_y = 0;
+        dx = - 1;
+        dy = - 1;
+        horizontal = FALSE;
+        break;
+    }
+
+  gdk_cairo_set_source_rgba (cr, &color);
+  if (horizontal)
+    for (y = start_y; y != end_y + dy; y += dy)
+      {
+        for (x = start_x; x != end_x + dx; x += dx)
+          {
+            text = g_strdup_printf ("%d", i++);
+            pango_layout_set_text (layout, text, -1);
+            g_free (text);
+            pango_layout_get_size (layout, &layout_w, &layout_h);
+            cairo_save (cr);
+            cairo_translate (cr,
+                             x * page_width,
+                             y * page_height + (page_height - layout_h / 1024.0) / 2);
+
+            pango_cairo_show_layout (cr, layout);
+            cairo_restore (cr);
+          }
+      }
+  else
+    for (x = start_x; x != end_x + dx; x += dx)
+      {
+        for (y = start_y; y != end_y + dy; y += dy)
+          {
+            text = g_strdup_printf ("%d", i++);
+            pango_layout_set_text (layout, text, -1);
+            g_free (text);
+            pango_layout_get_size (layout, &layout_w, &layout_h);
+            cairo_save (cr);
+            cairo_translate (cr,
+                             x * page_width,
+                             y * page_height + (page_height - layout_h / 1024.0) / 2);
+
+            pango_cairo_show_layout (cr, layout);
+            cairo_restore (cr);
+          }
+      }
+
+  g_object_unref (layout);
+
+  style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
+  color = *gtk_css_color_value_get_rgba (style->core->color);
+
+  if (page_setup != NULL)
+    {
+      PangoContext *pango_c = NULL;
+      PangoFontDescription *pango_f = NULL;
+      int font_size = 12 * PANGO_SCALE;
+
+      pos_x += 1;
+      pos_y += 1;
+
+      if (pages_per_sheet == 2 || pages_per_sheet == 6)
+        {
+          paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
+          paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
+        }
+      else
+        {
+          paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
+          paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
+        }
+
+      cairo_restore (cr);
+      cairo_save (cr);
+
+      layout = pango_cairo_create_layout (cr);
+
+      font = pango_font_description_new ();
+      pango_font_description_set_family (font, "sans");
+
+      pango_c = gtk_widget_get_pango_context (widget);
+      if (pango_c != NULL)
+        {
+          pango_f = pango_context_get_font_description (pango_c);
+          if (pango_f != NULL)
+            font_size = pango_font_description_get_size (pango_f);
+        }
+
+      pango_font_description_set_size (font, font_size);
+      pango_layout_set_font_description (layout, font);
+      pango_font_description_free (font);
+
+      pango_layout_set_width (layout, -1);
+      pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+
+      if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
+        text = g_strdup_printf ("%.1f mm", paper_height);
+      else
+        text = g_strdup_printf ("%.2f inch", paper_height);
+
+      pango_layout_set_text (layout, text, -1);
+      g_free (text);
+      pango_layout_get_size (layout, &layout_w, &layout_h);
+
+      ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
+
+      if (ltr)
+        cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
+                             (height - layout_h / PANGO_SCALE) / 2);
+      else
+        cairo_translate (cr, pos_x + w + 2 * RULER_DISTANCE,
+                             (height - layout_h / PANGO_SCALE) / 2);
+
+      gdk_cairo_set_source_rgba (cr, &color);
+      pango_cairo_show_layout (cr, layout);
+
+      cairo_restore (cr);
+      cairo_save (cr);
+
+      if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
+        text = g_strdup_printf ("%.1f mm", paper_width);
+      else
+        text = g_strdup_printf ("%.2f inch", paper_width);
+
+      pango_layout_set_text (layout, text, -1);
+      g_free (text);
+      pango_layout_get_size (layout, &layout_w, &layout_h);
+
+      cairo_translate (cr, (width - layout_w / PANGO_SCALE) / 2,
+                           pos_y + h + 2 * RULER_DISTANCE);
+
+      gdk_cairo_set_source_rgba (cr, &color);
+      pango_cairo_show_layout (cr, layout);
+
+      g_object_unref (layout);
+
+      cairo_restore (cr);
+
+      cairo_set_line_width (cr, 1);
+
+      gdk_cairo_set_source_rgba (cr, &color);
+
+      if (ltr)
+        {
+          cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
+          cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
+          cairo_stroke (cr);
+
+          cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
+          cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
+          cairo_stroke (cr);
+
+          cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
+          cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
+          cairo_stroke (cr);
+        }
+      else
+        {
+          cairo_move_to (cr, pos_x + w + RULER_DISTANCE, pos_y);
+          cairo_line_to (cr, pos_x + w + RULER_DISTANCE, pos_y + h);
+          cairo_stroke (cr);
+
+          cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
+          cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
+          cairo_stroke (cr);
+
+          cairo_move_to (cr, pos_x + w + RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
+          cairo_line_to (cr, pos_x + w + RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
+          cairo_stroke (cr);
+        }
+
+      cairo_move_to (cr, pos_x, pos_y + h + RULER_DISTANCE);
+      cairo_line_to (cr, pos_x + w, pos_y + h + RULER_DISTANCE);
+      cairo_stroke (cr);
+
+      cairo_move_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
+      cairo_line_to (cr, pos_x - 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
+      cairo_stroke (cr);
+
+      cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE - RULER_RADIUS);
+      cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + RULER_DISTANCE + RULER_RADIUS);
+      cairo_stroke (cr);
+    }
+}
+
+static void
+redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
+{
+  if (dialog->page_layout_preview)
+    gtk_widget_queue_draw (dialog->page_layout_preview);
+}
+
+static void
+update_number_up_layout (GtkPrintUnixDialog *dialog)
+{
+  GtkPrintCapabilities       caps;
+  GtkPrinterOptionSet       *set;
+  GtkNumberUpLayout          layout;
+  GtkPrinterOption          *option;
+  GtkPrinterOption          *old_option;
+  GtkPageOrientation         page_orientation;
+
+  set = dialog->options;
+
+  caps = dialog->manual_capabilities | dialog->printer_capabilities;
+
+  if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
+    {
+      if (dialog->number_up_layout_n_option == NULL)
+        {
+          dialog->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
+          if (dialog->number_up_layout_n_option == NULL)
+            {
+              const char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
+               /* Translators: These strings name the possible arrangements of
+                * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
+                */
+              const char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
+                                                    N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
+                                                    N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
+                                                    N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
+              int i;
+
+              dialog->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
+                                                                        _("Page Ordering"),
+                                                                        GTK_PRINTER_OPTION_TYPE_PICKONE);
+              gtk_printer_option_allocate_choices (dialog->number_up_layout_n_option, 8);
+
+              for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
+                {
+                  dialog->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
+                  dialog->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
+                }
+            }
+          g_object_ref (dialog->number_up_layout_n_option);
+
+          dialog->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
+                                                                    _("Page Ordering"),
+                                                                    GTK_PRINTER_OPTION_TYPE_PICKONE);
+          gtk_printer_option_allocate_choices (dialog->number_up_layout_2_option, 2);
+        }
+
+      page_orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+      if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+          page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+        {
+          if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
+                 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[2]))
+            {
+              g_free (dialog->number_up_layout_2_option->choices_display[0]);
+              g_free (dialog->number_up_layout_2_option->choices_display[1]);
+              dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
+              dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[2];
+              dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
+              dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
+            }
+        }
+      else
+        {
+          if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
+                 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[1]))
+            {
+              g_free (dialog->number_up_layout_2_option->choices_display[0]);
+              g_free (dialog->number_up_layout_2_option->choices_display[1]);
+              dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
+              dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[1];
+              dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
+              dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
+            }
+        }
+
+      layout = dialog_get_number_up_layout (dialog);
+
+      old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
+      if (old_option != NULL)
+        gtk_printer_option_set_remove (set, old_option);
+
+      if (dialog_get_pages_per_sheet (dialog) != 1)
+        {
+          GEnumClass *enum_class;
+          GEnumValue *enum_value;
+          enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
+
+          if (dialog_get_pages_per_sheet (dialog) == 2)
+            {
+              option = dialog->number_up_layout_2_option;
+
+              switch (layout)
+                {
+                case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+                case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
+                  break;
+
+                case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+                case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
+                  break;
+
+                case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+                case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
+                  break;
+
+                case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+                case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+                  enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
+                  break;
+
+                default:
+                  g_assert_not_reached();
+                  enum_value = NULL;
+                }
+            }
+          else
+            {
+              option = dialog->number_up_layout_n_option;
+
+              enum_value = g_enum_get_value (enum_class, layout);
+            }
+
+          g_assert (enum_value != NULL);
+          gtk_printer_option_set (option, enum_value->value_nick);
+          g_type_class_unref (enum_class);
+
+          gtk_printer_option_set_add (set, option);
+        }
+    }
+
+  setup_option (dialog, "gtk-n-up-layout", dialog->number_up_layout);
+
+  if (dialog->number_up_layout != NULL)
+    gtk_widget_set_sensitive (GTK_WIDGET (dialog->number_up_layout),
+                              (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
+                              (dialog_get_pages_per_sheet (dialog) > 1));
+}
+
+static void
+custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
+                                 int        response_id,
+                                 gpointer   user_data)
+{
+  GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (user_data);
+
+  dialog->internal_page_setup_change = TRUE;
+  gtk_print_load_custom_papers (dialog->custom_paper_list);
+  update_paper_sizes (dialog);
+  dialog->internal_page_setup_change = FALSE;
+
+  if (dialog->page_setup_set)
+    {
+      GListModel *model;
+      guint n, i;
+
+      model = G_LIST_MODEL (dialog->custom_paper_list);
+      n = g_list_model_get_n_items (model);
+      for (i = 0; i < n; i++)
+        {
+          GtkPageSetup *page_setup = g_list_model_get_item (model, i);
+
+          if (g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
+                         gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (dialog->page_setup))) == 0)
+            gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+
+          g_clear_object (&page_setup);
+        }
+    }
+
+  gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
+}
+
+static void
+orientation_changed (GObject            *object,
+                     GParamSpec         *pspec,
+                     GtkPrintUnixDialog *dialog)
+{
+  GtkPageOrientation orientation;
+  GtkPageSetup *page_setup;
+
+  if (dialog->internal_page_setup_change)
+    return;
+
+  orientation = (GtkPageOrientation) gtk_drop_down_get_selected (GTK_DROP_DOWN (dialog->orientation_combo));
+
+  if (dialog->page_setup)
+    {
+      page_setup = gtk_page_setup_copy (dialog->page_setup);
+      if (page_setup)
+        gtk_page_setup_set_orientation (page_setup, orientation);
+
+      gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+    }
+
+  redraw_page_layout_preview (dialog);
+}
+
+static void
+paper_size_changed (GtkDropDown *combo_box,
+                    GParamSpec *pspec,
+                    GtkPrintUnixDialog *dialog)
+{
+  GtkPageSetup *page_setup, *last_page_setup;
+  GtkPageOrientation orientation;
+  guint selected;
+
+  if (dialog->internal_page_setup_change)
+    return;
+
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (combo_box));
+  if (selected != GTK_INVALID_LIST_POSITION)
+    {
+      GListModel *papers, *model;
+
+      papers = gtk_drop_down_get_model (GTK_DROP_DOWN (dialog->paper_size_combo));
+      page_setup = g_list_model_get_item (papers, selected);
+      model = gtk_flatten_list_model_get_model_for_item (GTK_FLATTEN_LIST_MODEL (papers), selected);
+
+      if (model == G_LIST_MODEL (dialog->manage_papers_list))
+        {
+          GtkWidget *custom_paper_dialog;
+
+          /* Change from "manage" menu item to last value */
+          if (dialog->page_setup)
+            last_page_setup = g_object_ref (dialog->page_setup);
+          else
+            last_page_setup = gtk_page_setup_new (); /* "good" default */
+
+          if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
+            set_paper_size (dialog, last_page_setup, TRUE, TRUE);
+          g_object_unref (last_page_setup);
+
+          /* And show the custom paper dialog */
+          custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
+          g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
+          gtk_window_present (GTK_WINDOW (custom_paper_dialog));
+
+          g_object_unref (page_setup);
+
+          return;
+        }
+
+      if (dialog->page_setup)
+        orientation = gtk_page_setup_get_orientation (dialog->page_setup);
+      else
+        orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
+
+      gtk_page_setup_set_orientation (page_setup, orientation);
+      gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
+
+      g_object_unref (page_setup);
+    }
+
+  redraw_page_layout_preview (dialog);
+}
+
+/**
+ * gtk_print_unix_dialog_new:
+ * @title: (nullable): Title of the dialog
+ * @parent: (nullable): Transient parent of the dialog
+ *
+ * Creates a new `GtkPrintUnixDialog`.
+ *
+ * Returns: a new `GtkPrintUnixDialog`
+ */
+GtkWidget *
+gtk_print_unix_dialog_new (const char *title,
+                           GtkWindow   *parent)
+{
+  GtkWidget *result;
+
+  result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
+                         "transient-for", parent,
+                         "title", title ? title : _("Print"),
+                         NULL);
+
+  return result;
+}
+
+/**
+ * gtk_print_unix_dialog_get_selected_printer: (attributes org.gtk.Method.get_property=selected-printer)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the currently selected printer.
+ *
+ * Returns: (transfer none) (nullable): the currently selected printer
+ */
+GtkPrinter *
+gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+  return dialog->current_printer;
+}
+
+/**
+ * gtk_print_unix_dialog_set_page_setup: (attributes org.gtk.Method.set_property=page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @page_setup: a `GtkPageSetup`
+ *
+ * Sets the page setup of the `GtkPrintUnixDialog`.
+ */
+void
+gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
+                                      GtkPageSetup       *page_setup)
+{
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
+
+  if (dialog->page_setup != page_setup)
+    {
+      g_clear_object (&dialog->page_setup);
+      dialog->page_setup = g_object_ref (page_setup);
+
+      dialog->page_setup_set = TRUE;
+
+      g_object_notify (G_OBJECT (dialog), "page-setup");
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_page_setup: (attributes org.gtk.Method.get_property=page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the page setup that is used by the `GtkPrintUnixDialog`.
+ *
+ * Returns: (transfer none): the page setup of @dialog.
+ */
+GtkPageSetup *
+gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+  return dialog->page_setup;
+}
+
+/**
+ * gtk_print_unix_dialog_get_page_setup_set:
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether a page setup was set by the user.
+ *
+ * Returns: whether a page setup was set by user.
+ */
+gboolean
+gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+  return dialog->page_setup_set;
+}
+
+/**
+ * gtk_print_unix_dialog_set_current_page: (attributes org.gtk.Method.set_property=current-page)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @current_page: the current page number.
+ *
+ * Sets the current page number.
+ *
+ * If @current_page is not -1, this enables the current page choice
+ * for the range of pages to print.
+ */
+void
+gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
+                                        int                 current_page)
+{
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+  if (dialog->current_page != current_page)
+    {
+      dialog->current_page = current_page;
+
+      if (dialog->current_page_radio)
+        gtk_widget_set_sensitive (dialog->current_page_radio, current_page != -1);
+
+      g_object_notify (G_OBJECT (dialog), "current-page");
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_current_page: (attributes org.gtk.Method.get_property=current-page)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the current page of the `GtkPrintUnixDialog`.
+ *
+ * Returns: the current page of @dialog
+ */
+int
+gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
+
+  return dialog->current_page;
+}
+
+static gboolean
+set_active_printer (GtkPrintUnixDialog *dialog,
+                    const char         *printer_name)
+{
+  GListModel *model;
+  GtkPrinter *printer;
+  guint i;
+
+  model = G_LIST_MODEL (gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
+
+  for (i = 0; i < g_list_model_get_n_items (model); i++)
+    {
+      printer = g_list_model_get_item (model, i);
+
+      if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
+        {
+          gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), i);
+
+          g_free (dialog->waiting_for_printer);
+          dialog->waiting_for_printer = NULL;
+
+          g_object_unref (printer);
+          return TRUE;
+        }
+
+      g_object_unref (printer);
+    }
+
+  return FALSE;
+}
+
+/**
+ * gtk_print_unix_dialog_set_settings: (attributes org.gtk.Method.set_property=print-settings)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @settings: (nullable): a `GtkPrintSettings`
+ *
+ * Sets the `GtkPrintSettings` for the `GtkPrintUnixDialog`.
+ *
+ * Typically, this is used to restore saved print settings
+ * from a previous print operation before the print dialog
+ * is shown.
+ */
+void
+gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
+                                    GtkPrintSettings   *settings)
+{
+  const char *printer;
+  GtkPageRange *ranges;
+  int num_ranges;
+
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+  g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
+
+  if (settings != NULL)
+    {
+      dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
+      dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
+      dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
+      dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
+      dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
+      dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
+      ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
+      if (ranges)
+        {
+          dialog_set_page_ranges (dialog, ranges, num_ranges);
+          g_free (ranges);
+        }
+
+      dialog->format_for_printer =
+        g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
+    }
+
+  if (dialog->initial_settings)
+    g_object_unref (dialog->initial_settings);
+
+  dialog->initial_settings = settings;
+
+  g_free (dialog->waiting_for_printer);
+  dialog->waiting_for_printer = NULL;
+
+  if (settings)
+    {
+      g_object_ref (settings);
+
+      printer = gtk_print_settings_get_printer (settings);
+
+      if (printer && !set_active_printer (dialog, printer))
+        dialog->waiting_for_printer = g_strdup (printer);
+    }
+
+  g_object_notify (G_OBJECT (dialog), "print-settings");
+}
+
+/**
+ * gtk_print_unix_dialog_get_settings: (attributes org.gtk.Method.set_property=print-settings)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets a new `GtkPrintSettings` object that represents the
+ * current values in the print dialog.
+ *
+ * Note that this creates a new object, and you need to unref
+ * it if don’t want to keep it.
+ *
+ * Returns: (transfer full): a new `GtkPrintSettings` object with the values from @dialog
+ */
+GtkPrintSettings *
+gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
+{
+  GtkPrintSettings *settings;
+  GtkPrintPages print_pages;
+  GtkPageRange *ranges;
+  int n_ranges;
+
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
+
+  settings = gtk_print_settings_new ();
+
+  if (dialog->current_printer)
+    gtk_print_settings_set_printer (settings,
+                                    gtk_printer_get_name (dialog->current_printer));
+  else
+    gtk_print_settings_set_printer (settings, "default");
+
+  gtk_print_settings_set (settings, "format-for-printer",
+                          dialog->format_for_printer);
+
+  gtk_print_settings_set_collate (settings,
+                                  dialog_get_collate (dialog));
+
+  gtk_print_settings_set_reverse (settings,
+                                  dialog_get_reverse (dialog));
+
+  gtk_print_settings_set_n_copies (settings,
+                                   dialog_get_n_copies (dialog));
+
+  gtk_print_settings_set_scale (settings,
+                                dialog_get_scale (dialog));
+
+  gtk_print_settings_set_page_set (settings,
+                                   dialog_get_page_set (dialog));
+
+  print_pages = dialog_get_print_pages (dialog);
+  gtk_print_settings_set_print_pages (settings, print_pages);
+
+  ranges = dialog_get_page_ranges (dialog, &n_ranges);
+  if (ranges)
+    {
+      gtk_print_settings_set_page_ranges (settings, ranges, n_ranges);
+      g_free (ranges);
+    }
+
+  /* TODO: print when. How to handle? */
+
+  if (dialog->current_printer)
+    _gtk_printer_get_settings_from_options (dialog->current_printer,
+                                            dialog->options,
+                                            settings);
+
+  return settings;
+}
+
+/**
+ * gtk_print_unix_dialog_add_custom_tab:
+ * @dialog: a `GtkPrintUnixDialog`
+ * @child: the widget to put in the custom tab
+ * @tab_label: the widget to use as tab label
+ *
+ * Adds a custom tab to the print dialog.
+ */
+void
+gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
+                                      GtkWidget          *child,
+                                      GtkWidget          *tab_label)
+{
+  gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->notebook),
+                            child, tab_label, 2);
+  gtk_widget_set_visible (child, TRUE);
+  gtk_widget_set_visible (tab_label, TRUE);
+}
+
+/**
+ * gtk_print_unix_dialog_set_manual_capabilities: (attributes org.gtk.Method.set_property=manual-capabilities)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @capabilities: the printing capabilities of your application
+ *
+ * This lets you specify the printing capabilities your application
+ * supports.
+ *
+ * For instance, if you can handle scaling the output then you pass
+ * %GTK_PRINT_CAPABILITY_SCALE. If you don’t pass that, then the dialog
+ * will only let you select the scale if the printing system automatically
+ * handles scaling.
+ */
+void
+gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog   *dialog,
+                                               GtkPrintCapabilities  capabilities)
+{
+  if (dialog->manual_capabilities != capabilities)
+    {
+      dialog->manual_capabilities = capabilities;
+      update_dialog_from_capabilities (dialog);
+
+      if (dialog->current_printer)
+        {
+          g_clear_object (&dialog->current_printer);
+          selected_printer_changed (dialog);
+       }
+
+      g_object_notify (G_OBJECT (dialog), "manual-capabilities");
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_manual_capabilities: (attributes org.gtk.Method.get_property=manual-capabilities)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets the capabilities that have been set on this `GtkPrintUnixDialog`.
+ *
+ * Returns: the printing capabilities
+ */
+GtkPrintCapabilities
+gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+  return dialog->manual_capabilities;
+}
+
+/**
+ * gtk_print_unix_dialog_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @support_selection: %TRUE to allow print selection
+ *
+ * Sets whether the print dialog allows user to print a selection.
+ */
+void
+gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
+                                             gboolean            support_selection)
+{
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+  support_selection = support_selection != FALSE;
+  if (dialog->support_selection != support_selection)
+    {
+      dialog->support_selection = support_selection;
+
+      if (dialog->selection_radio)
+        {
+          gtk_widget_set_visible (dialog->selection_radio, support_selection);
+          gtk_widget_set_sensitive (dialog->selection_radio, support_selection && dialog->has_selection);
+        }
+
+      g_object_notify (G_OBJECT (dialog), "support-selection");
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether the print dialog allows user to print a selection.
+ *
+ * Returns: whether the application supports print of selection
+ */
+gboolean
+gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+  return dialog->support_selection;
+}
+
+/**
+ * gtk_print_unix_dialog_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @has_selection: %TRUE indicates that a selection exists
+ *
+ * Sets whether a selection exists.
+ */
+void
+gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
+                                         gboolean            has_selection)
+{
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+  has_selection = has_selection != FALSE;
+  if (dialog->has_selection != has_selection)
+    {
+      dialog->has_selection = has_selection;
+
+      if (dialog->selection_radio)
+        {
+          if (dialog->support_selection)
+            gtk_widget_set_sensitive (dialog->selection_radio, has_selection);
+          else
+            gtk_widget_set_sensitive (dialog->selection_radio, FALSE);
+        }
+
+      g_object_notify (G_OBJECT (dialog), "has-selection");
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether there is a selection.
+ *
+ * Returns: whether there is a selection
+ */
+gboolean
+gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+  return dialog->has_selection;
+}
+
+/**
+ * gtk_print_unix_dialog_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ * @embed: embed page setup selection
+ *
+ * Embed page size combo box and orientation combo box into page setup page.
+ */
+void
+gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
+                                            gboolean            embed)
+{
+  g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
+
+  embed = embed != FALSE;
+  if (dialog->embed_page_setup != embed)
+    {
+      dialog->embed_page_setup = embed;
+
+      gtk_widget_set_sensitive (dialog->paper_size_combo, dialog->embed_page_setup);
+      gtk_widget_set_sensitive (dialog->orientation_combo, dialog->embed_page_setup);
+
+      if (dialog->embed_page_setup)
+        {
+          if (dialog->paper_size_combo != NULL)
+            g_signal_connect (dialog->paper_size_combo, "notify::selected", G_CALLBACK (paper_size_changed), dialog);
+
+          if (dialog->orientation_combo)
+            g_signal_connect (dialog->orientation_combo, "notify::selected", G_CALLBACK (orientation_changed), dialog);
+        }
+      else
+        {
+          if (dialog->paper_size_combo != NULL)
+            g_signal_handlers_disconnect_by_func (dialog->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
+
+          if (dialog->orientation_combo)
+            g_signal_handlers_disconnect_by_func (dialog->orientation_combo, G_CALLBACK (orientation_changed), dialog);
+        }
+
+      dialog->internal_page_setup_change = TRUE;
+      update_paper_sizes (dialog);
+      dialog->internal_page_setup_change = FALSE;
+    }
+}
+
+/**
+ * gtk_print_unix_dialog_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
+ * @dialog: a `GtkPrintUnixDialog`
+ *
+ * Gets whether to embed the page setup.
+ *
+ * Returns: whether to embed the page setup
+ */
+gboolean
+gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
+
+  return dialog->embed_page_setup;
+}
diff --git a/gtk/print/gtkprintunixdialog.h b/gtk/print/gtkprintunixdialog.h
new file mode 100644 (file)
index 0000000..48a5ec7
--- /dev/null
@@ -0,0 +1,91 @@
+/* GtkPrintUnixDialog
+ * Copyright (C) 2006 John (J5) Palmieri <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_UNIX_PRINT_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtkunixprint.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+#include <gtk/print/gtkprinter.h>
+#include <gtk/print/gtkprintjob.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PRINT_UNIX_DIALOG                  (gtk_print_unix_dialog_get_type ())
+#define GTK_PRINT_UNIX_DIALOG(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialog))
+#define GTK_IS_PRINT_UNIX_DIALOG(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PRINT_UNIX_DIALOG))
+
+
+typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog;
+
+
+GDK_AVAILABLE_IN_ALL
+GType                gtk_print_unix_dialog_get_type                (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkWidget *          gtk_print_unix_dialog_new                     (const char *title,
+                                                                    GtkWindow   *parent);
+
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_page_setup          (GtkPrintUnixDialog *dialog,
+                                                                   GtkPageSetup       *page_setup);
+GDK_AVAILABLE_IN_ALL
+GtkPageSetup *       gtk_print_unix_dialog_get_page_setup          (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_current_page        (GtkPrintUnixDialog *dialog,
+                                                                   int                 current_page);
+GDK_AVAILABLE_IN_ALL
+int                  gtk_print_unix_dialog_get_current_page        (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_settings            (GtkPrintUnixDialog *dialog,
+                                                                   GtkPrintSettings   *settings);
+GDK_AVAILABLE_IN_ALL
+GtkPrintSettings *   gtk_print_unix_dialog_get_settings            (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+GtkPrinter *         gtk_print_unix_dialog_get_selected_printer    (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_add_custom_tab          (GtkPrintUnixDialog *dialog,
+                                                                   GtkWidget          *child,
+                                                                   GtkWidget          *tab_label);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
+                                                                   GtkPrintCapabilities capabilities);
+GDK_AVAILABLE_IN_ALL
+GtkPrintCapabilities gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog  *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_support_selection   (GtkPrintUnixDialog  *dialog,
+                                                                   gboolean             support_selection);
+GDK_AVAILABLE_IN_ALL
+gboolean             gtk_print_unix_dialog_get_support_selection   (GtkPrintUnixDialog  *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_has_selection       (GtkPrintUnixDialog  *dialog,
+                                                                   gboolean             has_selection);
+GDK_AVAILABLE_IN_ALL
+gboolean             gtk_print_unix_dialog_get_has_selection       (GtkPrintUnixDialog  *dialog);
+GDK_AVAILABLE_IN_ALL
+void                 gtk_print_unix_dialog_set_embed_page_setup    (GtkPrintUnixDialog *dialog,
+                                                                   gboolean            embed);
+GDK_AVAILABLE_IN_ALL
+gboolean             gtk_print_unix_dialog_get_embed_page_setup    (GtkPrintUnixDialog *dialog);
+GDK_AVAILABLE_IN_ALL
+gboolean             gtk_print_unix_dialog_get_page_setup_set      (GtkPrintUnixDialog *dialog);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPrintUnixDialog, g_object_unref)
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkprintutilsprivate.h b/gtk/print/gtkprintutilsprivate.h
new file mode 100644 (file)
index 0000000..9e63e91
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gdk/gdk.h>
+#include "gtkenums.h"
+
+
+G_BEGIN_DECLS
+
+#define MM_PER_INCH 25.4
+#define POINTS_PER_INCH 72
+
+double _gtk_print_convert_to_mm   (double len, GtkUnit unit);
+double _gtk_print_convert_from_mm (double len, GtkUnit unit);
+
+G_END_DECLS
+
diff --git a/gtk/print/gtkunixprint.h b/gtk/print/gtkunixprint.h
new file mode 100644 (file)
index 0000000..79158f1
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#define __GTK_UNIX_PRINT_H_INSIDE__
+
+#include <gtk/print/gtkpagesetupunixdialog.h>
+#include <gtk/print/gtkprinter.h>
+#include <gtk/print/gtkprintjob.h>
+#include <gtk/print/gtkprintunixdialog.h>
+
+#undef __GTK_UNIX_PRINT_H_INSIDE__
+
index 78312aabd6e4148a75b9e2771a0529895d624c50..79f4d085de3502364e3df0a08f759094353c1e1c 100644 (file)
@@ -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 (file)
index 0000000..e5c9d0b
--- /dev/null
@@ -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 (file)
index 0000000..d4f79e2
--- /dev/null
@@ -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 },
+};
+
index ed40db68aa7cf5a65f659d5d0fdb8a891f0f805a..aa9b5158789ff0e096dfa11bd7523ab14922a631 100644 (file)
@@ -45,9 +45,9 @@
 #include <gmodule.h>
 
 #include <gtk/gtk.h>
-#include <gtk/gtkprintbackendprivate.h>
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinterprivate.h>
+#include <gtk/print/gtkprintbackendprivate.h>
+#include <gtk/print/gtkunixprint.h>
+#include <gtk/print/gtkprinterprivate.h>
 #include <gtk/gtkprivate.h>
 
 #include "gtkprintbackendcups.h"
@@ -57,7 +57,7 @@
 #include "gtkcupssecretsutils.h"
 #include "gtkprintbackendutils.h"
 
-#include <gtkprintutilsprivate.h>
+#include <gtk/print/gtkprintutilsprivate.h>
 #include "gtkprivate.h"
 
 #ifdef HAVE_COLORD
index a37a571a35d7560e501bb7169b1e417e7d9317f1..b5ac6d3980e73994649f69f6ba0fcf54bfea84f3 100644 (file)
@@ -20,7 +20,7 @@
 #define __GTK_PRINT_BACKEND_CUPS_H__
 
 #include <glib-object.h>
-#include "gtkprintbackendprivate.h"
+#include "gtk/print/gtkprintbackendprivate.h"
 
 G_BEGIN_DECLS
 
index 739313064bbbfdf4e633b30a1e122805992511bb..eb0b00ce3b023a85922f53ec5bbe2f5b6a27e65b 100644 (file)
@@ -35,7 +35,7 @@
 #include <glib/gi18n-lib.h>
 
 #include "gtk/gtk.h"
-#include "gtk/gtkprinterprivate.h"
+#include "gtk/print/gtkprinterprivate.h"
 #include "gtk/gtkprivate.h"
 
 #include "gtkprintbackendfile.h"
index 0ca051b5ffff385963811cd99824f77968b8c5f2..280b901d00d58479af7577de506183e754df9e43 100644 (file)
@@ -21,7 +21,7 @@
 #define __GTK_PRINT_BACKEND_FILE_H__
 
 #include <glib-object.h>
-#include "gtkprintbackendprivate.h"
+#include "gtk/print/gtkprintbackendprivate.h"
 
 G_BEGIN_DECLS
 
index 81b6cfb9c82057315f9d3ca56a094ab4fd071c2e..fb67f6ac837153a7dc51c40bb8c51eb70930f769 100644 (file)
@@ -23,8 +23,8 @@
 #include <cups/ppd.h>
 #include "gtkcupsutils.h"
 
-#include <gtk/gtkunixprint.h>
-#include <gtk/gtkprinterprivate.h>
+#include <gtk/print/gtkunixprint.h>
+#include <gtk/print/gtkprinterprivate.h>
 
 #ifdef HAVE_COLORD
 #include <colord.h>