print: Move frontend sources
authorMatthias Clasen <mclasen@redhat.com>
Wed, 7 Jun 2023 02:52:12 +0000 (22:52 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Wed, 7 Jun 2023 03:21:19 +0000 (23:21 -0400)
Move the cross-platform printing sources
to the gtk/print subdirectory.

16 files changed:
gtk/gtkpagesetup.c [deleted file]
gtk/gtkpapersize.c [deleted file]
gtk/gtkprintcontext.c [deleted file]
gtk/gtkprintoperation.c [deleted file]
gtk/gtkprintoperationpreview.c [deleted file]
gtk/gtkprintsettings.c [deleted file]
gtk/gtkprintutils.c [deleted file]
gtk/meson.build
gtk/print/gtkpagesetup.c [new file with mode: 0644]
gtk/print/gtkpapersize.c [new file with mode: 0644]
gtk/print/gtkprintcontext.c [new file with mode: 0644]
gtk/print/gtkprintoperation.c [new file with mode: 0644]
gtk/print/gtkprintoperationpreview.c [new file with mode: 0644]
gtk/print/gtkprintsettings.c [new file with mode: 0644]
gtk/print/gtkprintutils.c [new file with mode: 0644]
gtk/print/meson.build

diff --git a/gtk/gtkpagesetup.c b/gtk/gtkpagesetup.c
deleted file mode 100644 (file)
index 5e77236..0000000
+++ /dev/null
@@ -1,876 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkpagesetup.c: Page Setup
- * 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 "print/gtkpagesetup.h"
-#include "gtkprintutilsprivate.h"
-#include "print/gtkprintoperation.h" /* for GtkPrintError */
-#include <glib/gi18n-lib.h>
-#include "gtktypebuiltins.h"
-
-/**
- * GtkPageSetup:
- *
- * A `GtkPageSetup` object stores the page size, orientation and margins.
- *
- * The idea is that you can get one of these from the page setup dialog
- * and then pass it to the `GtkPrintOperation` when printing.
- * The benefit of splitting this out of the `GtkPrintSettings` is that
- * these affect the actual layout of the page, and thus need to be set
- * long before user prints.
- *
- * ## Margins
- *
- * The margins specified in this object are the “print margins”, i.e. the
- * parts of the page that the printer cannot print on. These are different
- * from the layout margins that a word processor uses; they are typically
- * used to determine the minimal size for the layout margins.
- *
- * To obtain a `GtkPageSetup` use [ctor@Gtk.PageSetup.new] to get the defaults,
- * or use [func@Gtk.print_run_page_setup_dialog] to show the page setup dialog
- * and receive the resulting page setup.
- *
- * ## A page setup dialog
- *
- * ```c
- * static GtkPrintSettings *settings = NULL;
- * static GtkPageSetup *page_setup = NULL;
- *
- * static void
- * do_page_setup (void)
- * {
- *   GtkPageSetup *new_page_setup;
- *
- *   if (settings == NULL)
- *     settings = gtk_print_settings_new ();
- *
- *   new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (main_window),
- *                                                     page_setup, settings);
- *
- *   if (page_setup)
- *     g_object_unref (page_setup);
- *
- *   page_setup = new_page_setup;
- * }
- * ```
- */
-
-#define KEYFILE_GROUP_NAME "Page Setup"
-
-typedef struct _GtkPageSetupClass GtkPageSetupClass;
-
-#define GTK_IS_PAGE_SETUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PAGE_SETUP))
-#define GTK_PAGE_SETUP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PAGE_SETUP, GtkPageSetupClass))
-#define GTK_PAGE_SETUP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PAGE_SETUP, GtkPageSetupClass))
-
-struct _GtkPageSetup
-{
-  GObject parent_instance;
-
-  GtkPageOrientation orientation;
-  GtkPaperSize *paper_size;
-  /* These are stored in mm */
-  double top_margin, bottom_margin, left_margin, right_margin;
-};
-
-struct _GtkPageSetupClass
-{
-  GObjectClass parent_class;
-};
-
-G_DEFINE_TYPE (GtkPageSetup, gtk_page_setup, G_TYPE_OBJECT)
-
-static void
-gtk_page_setup_finalize (GObject *object)
-{
-  GtkPageSetup *setup = GTK_PAGE_SETUP (object);
-  
-  gtk_paper_size_free (setup->paper_size);
-  
-  G_OBJECT_CLASS (gtk_page_setup_parent_class)->finalize (object);
-}
-
-static void
-gtk_page_setup_init (GtkPageSetup *setup)
-{
-  setup->paper_size = gtk_paper_size_new (NULL);
-  setup->orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
-  setup->top_margin = gtk_paper_size_get_default_top_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->bottom_margin = gtk_paper_size_get_default_bottom_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->left_margin = gtk_paper_size_get_default_left_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->right_margin = gtk_paper_size_get_default_right_margin (setup->paper_size, GTK_UNIT_MM);
-}
-
-static void
-gtk_page_setup_class_init (GtkPageSetupClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->finalize = gtk_page_setup_finalize;
-}
-
-/**
- * gtk_page_setup_new:
- *
- * Creates a new `GtkPageSetup`.
- *
- * Returns: a new `GtkPageSetup`.
- */
-GtkPageSetup *
-gtk_page_setup_new (void)
-{
-  return g_object_new (GTK_TYPE_PAGE_SETUP, NULL);
-}
-
-/**
- * gtk_page_setup_copy:
- * @other: the `GtkPageSetup` to copy
- *
- * Copies a `GtkPageSetup`.
- *
- * Returns: (transfer full): a copy of @other
- */
-GtkPageSetup *
-gtk_page_setup_copy (GtkPageSetup *other)
-{
-  GtkPageSetup *copy;
-
-  copy = gtk_page_setup_new ();
-  copy->orientation = other->orientation;
-  gtk_paper_size_free (copy->paper_size);
-  copy->paper_size = gtk_paper_size_copy (other->paper_size);
-  copy->top_margin = other->top_margin;
-  copy->bottom_margin = other->bottom_margin;
-  copy->left_margin = other->left_margin;
-  copy->right_margin = other->right_margin;
-
-  return copy;
-}
-
-/**
- * gtk_page_setup_get_orientation:
- * @setup: a `GtkPageSetup`
- *
- * Gets the page orientation of the `GtkPageSetup`.
- *
- * Returns: the page orientation
- */
-GtkPageOrientation
-gtk_page_setup_get_orientation (GtkPageSetup *setup)
-{
-  return setup->orientation;
-}
-
-/**
- * gtk_page_setup_set_orientation:
- * @setup: a `GtkPageSetup`
- * @orientation: a `GtkPageOrientation` value
- *
- * Sets the page orientation of the `GtkPageSetup`.
- */
-void
-gtk_page_setup_set_orientation (GtkPageSetup       *setup,
-                               GtkPageOrientation  orientation)
-{
-  setup->orientation = orientation;
-}
-
-/**
- * gtk_page_setup_get_paper_size:
- * @setup: a `GtkPageSetup`
- *
- * Gets the paper size of the `GtkPageSetup`.
- *
- * Returns: (transfer none): the paper size
- */
-GtkPaperSize *
-gtk_page_setup_get_paper_size (GtkPageSetup *setup)
-{
-  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), NULL);
-
-  return setup->paper_size;
-}
-
-/**
- * gtk_page_setup_set_paper_size:
- * @setup: a `GtkPageSetup`
- * @size: a `GtkPaperSize`
- *
- * Sets the paper size of the `GtkPageSetup` without
- * changing the margins.
- *
- * See [method@Gtk.PageSetup.set_paper_size_and_default_margins].
- */
-void
-gtk_page_setup_set_paper_size (GtkPageSetup *setup,
-                              GtkPaperSize *size)
-{
-  GtkPaperSize *old_size;
-
-  g_return_if_fail (GTK_IS_PAGE_SETUP (setup));
-  g_return_if_fail (size != NULL);
-
-  old_size = setup->paper_size;
-
-  setup->paper_size = gtk_paper_size_copy (size);
-
-  if (old_size)
-    gtk_paper_size_free (old_size);
-}
-
-/**
- * gtk_page_setup_set_paper_size_and_default_margins:
- * @setup: a `GtkPageSetup`
- * @size: a `GtkPaperSize`
- *
- * Sets the paper size of the `GtkPageSetup` and modifies
- * the margins according to the new paper size.
- */
-void
-gtk_page_setup_set_paper_size_and_default_margins (GtkPageSetup *setup,
-                                                  GtkPaperSize *size)
-{
-  gtk_page_setup_set_paper_size (setup, size);
-  setup->top_margin = gtk_paper_size_get_default_top_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->bottom_margin = gtk_paper_size_get_default_bottom_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->left_margin = gtk_paper_size_get_default_left_margin (setup->paper_size, GTK_UNIT_MM);
-  setup->right_margin = gtk_paper_size_get_default_right_margin (setup->paper_size, GTK_UNIT_MM);
-}
-
-/**
- * gtk_page_setup_get_top_margin:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Gets the top margin in units of @unit.
- *
- * Returns: the top margin
- */
-double
-gtk_page_setup_get_top_margin (GtkPageSetup *setup,
-                              GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (setup->top_margin, unit);
-}
-
-/**
- * gtk_page_setup_set_top_margin:
- * @setup: a `GtkPageSetup`
- * @margin: the new top margin in units of @unit
- * @unit: the units for @margin
- *
- * Sets the top margin of the `GtkPageSetup`.
- */
-void
-gtk_page_setup_set_top_margin (GtkPageSetup *setup,
-                              double        margin,
-                              GtkUnit       unit)
-{
-  setup->top_margin = _gtk_print_convert_to_mm (margin, unit);
-}
-
-/**
- * gtk_page_setup_get_bottom_margin:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Gets the bottom margin in units of @unit.
- *
- * Returns: the bottom margin
- */
-double
-gtk_page_setup_get_bottom_margin (GtkPageSetup *setup,
-                                 GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (setup->bottom_margin, unit);
-}
-
-/**
- * gtk_page_setup_set_bottom_margin:
- * @setup: a `GtkPageSetup`
- * @margin: the new bottom margin in units of @unit
- * @unit: the units for @margin
- *
- * Sets the bottom margin of the `GtkPageSetup`.
- */
-void
-gtk_page_setup_set_bottom_margin (GtkPageSetup *setup,
-                                 double        margin,
-                                 GtkUnit       unit)
-{
-  setup->bottom_margin = _gtk_print_convert_to_mm (margin, unit);
-}
-
-/**
- * gtk_page_setup_get_left_margin:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Gets the left margin in units of @unit.
- *
- * Returns: the left margin
- */
-double
-gtk_page_setup_get_left_margin (GtkPageSetup *setup,
-                               GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (setup->left_margin, unit);
-}
-
-/**
- * gtk_page_setup_set_left_margin:
- * @setup: a `GtkPageSetup`
- * @margin: the new left margin in units of @unit
- * @unit: the units for @margin
- *
- * Sets the left margin of the `GtkPageSetup`.
- */
-void
-gtk_page_setup_set_left_margin (GtkPageSetup *setup,
-                               double        margin,
-                               GtkUnit       unit)
-{
-  setup->left_margin = _gtk_print_convert_to_mm (margin, unit);
-}
-
-/**
- * gtk_page_setup_get_right_margin:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Gets the right margin in units of @unit.
- *
- * Returns: the right margin
- */
-double
-gtk_page_setup_get_right_margin (GtkPageSetup *setup,
-                                GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (setup->right_margin, unit);
-}
-
-/**
- * gtk_page_setup_set_right_margin:
- * @setup: a `GtkPageSetup`
- * @margin: the new right margin in units of @unit
- * @unit: the units for @margin
- *
- * Sets the right margin of the `GtkPageSetup`.
- */
-void
-gtk_page_setup_set_right_margin (GtkPageSetup *setup,
-                                double        margin,
-                                GtkUnit       unit)
-{
-  setup->right_margin = _gtk_print_convert_to_mm (margin, unit);
-}
-
-/**
- * gtk_page_setup_get_paper_width:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Returns the paper width in units of @unit.
- *
- * Note that this function takes orientation,
- * but not margins into consideration.
- * See [method@Gtk.PageSetup.get_page_width].
- *
- * Returns: the paper width.
- */
-double
-gtk_page_setup_get_paper_width (GtkPageSetup *setup,
-                               GtkUnit       unit)
-{
-  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-    return gtk_paper_size_get_width (setup->paper_size, unit);
-  else
-    return gtk_paper_size_get_height (setup->paper_size, unit);
-}
-
-/**
- * gtk_page_setup_get_paper_height:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Returns the paper height in units of @unit.
- *
- * Note that this function takes orientation,
- * but not margins into consideration.
- * See [method@Gtk.PageSetup.get_page_height].
- *
- * Returns: the paper height.
- */
-double
-gtk_page_setup_get_paper_height (GtkPageSetup *setup,
-                                GtkUnit       unit)
-{
-  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-    return gtk_paper_size_get_height (setup->paper_size, unit);
-  else
-    return gtk_paper_size_get_width (setup->paper_size, unit);
-}
-
-/**
- * gtk_page_setup_get_page_width:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Returns the page width in units of @unit.
- *
- * Note that this function takes orientation
- * and margins into consideration.
- * See [method@Gtk.PageSetup.get_paper_width].
- *
- * Returns: the page width.
- */
-double
-gtk_page_setup_get_page_width (GtkPageSetup *setup,
-                              GtkUnit       unit)
-{
-  double width;
-
-  width = gtk_page_setup_get_paper_width (setup, GTK_UNIT_MM);
-  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-    width -= setup->left_margin + setup->right_margin;
-  else
-    width -= setup->top_margin + setup->bottom_margin;
-
-  return _gtk_print_convert_from_mm (width, unit);
-}
-
-/**
- * gtk_page_setup_get_page_height:
- * @setup: a `GtkPageSetup`
- * @unit: the unit for the return value
- *
- * Returns the page height in units of @unit.
- *
- * Note that this function takes orientation
- * and margins into consideration.
- * See [method@Gtk.PageSetup.get_paper_height].
- *
- * Returns: the page height.
- */
-double
-gtk_page_setup_get_page_height (GtkPageSetup *setup,
-                               GtkUnit       unit)
-{
-  double height;
-
-  height = gtk_page_setup_get_paper_height (setup, GTK_UNIT_MM);
-  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-    height -= setup->top_margin + setup->bottom_margin;
-  else
-    height -= setup->left_margin + setup->right_margin;
-
-  return _gtk_print_convert_from_mm (height, unit);
-}
-
-/**
- * gtk_page_setup_load_file:
- * @setup: a `GtkPageSetup`
- * @file_name: (type filename): the filename to read the page setup from
- * @error: (nullable): return location for an error
- *
- * Reads the page setup from the file @file_name.
- *
- * See [method@Gtk.PageSetup.to_file].
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_page_setup_load_file (GtkPageSetup *setup,
-                          const char   *file_name,
-                         GError      **error)
-{
-  gboolean retval = FALSE;
-  GKeyFile *key_file;
-
-  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
-  g_return_val_if_fail (file_name != NULL, FALSE);
-
-  key_file = g_key_file_new ();
-
-  if (g_key_file_load_from_file (key_file, file_name, 0, error) &&
-      gtk_page_setup_load_key_file (setup, key_file, NULL, error))
-    retval = TRUE;
-
-  g_key_file_free (key_file);
-
-  return retval;
-}
-
-/**
- * gtk_page_setup_new_from_file:
- * @file_name: (type filename): the filename to read the page setup from
- * @error: (nullable): return location for an error
- *
- * Reads the page setup from the file @file_name.
- *
- * Returns a new `GtkPageSetup` object with the restored
- * page setup, or %NULL if an error occurred.
- * See [method@Gtk.PageSetup.to_file].
- *
- * Returns: the restored `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_page_setup_new_from_file (const char   *file_name,
-                             GError      **error)
-{
-  GtkPageSetup *setup = gtk_page_setup_new ();
-
-  if (!gtk_page_setup_load_file (setup, file_name, error))
-    {
-      g_object_unref (setup);
-      setup = NULL;
-    }
-
-  return setup;
-}
-
-/* something like this should really be in gobject! */
-static guint
-string_to_enum (GType type,
-                const char *enum_string)
-{
-  GEnumClass *enum_class;
-  const GEnumValue *value;
-  guint retval = 0;
-
-  g_return_val_if_fail (enum_string != NULL, 0);
-
-  enum_class = g_type_class_ref (type);
-  value = g_enum_get_value_by_nick (enum_class, enum_string);
-  if (value)
-    retval = value->value;
-
-  g_type_class_unref (enum_class);
-
-  return retval;
-}
-
-/**
- * gtk_page_setup_load_key_file:
- * @setup: a `GtkPageSetup`
- * @key_file: the `GKeyFile` to retrieve the page_setup from
- * @group_name: (nullable): the name of the group in the key_file to read
- *   to use the default name “Page Setup”
- * @error: (nullable): return location for an error
- *
- * Reads the page setup from the group @group_name in the key file
- * @key_file.
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_page_setup_load_key_file (GtkPageSetup *setup,
-                              GKeyFile     *key_file,
-                              const char   *group_name,
-                              GError      **error)
-{
-  GtkPaperSize *paper_size;
-  double top, bottom, left, right;
-  char *orientation = NULL, *freeme = NULL;
-  gboolean retval = FALSE;
-  GError *err = NULL;
-
-  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
-  g_return_val_if_fail (key_file != NULL, FALSE);
-
-  if (!group_name)
-    group_name = KEYFILE_GROUP_NAME;
-
-  if (!g_key_file_has_group (key_file, group_name))
-    {
-      g_set_error_literal (error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_INVALID_FILE,
-                           _("Not a valid page setup file"));
-      goto out;
-    }
-
-#define GET_DOUBLE(kf, group, name, v) \
-  v = g_key_file_get_double (kf, group, name, &err); \
-  if (err != NULL) \
-    { \
-      g_propagate_error (error, err);\
-      goto out;\
-    }
-
-  GET_DOUBLE (key_file, group_name, "MarginTop", top);
-  GET_DOUBLE (key_file, group_name, "MarginBottom", bottom);
-  GET_DOUBLE (key_file, group_name, "MarginLeft", left);
-  GET_DOUBLE (key_file, group_name, "MarginRight", right);
-
-#undef GET_DOUBLE
-
-  paper_size = gtk_paper_size_new_from_key_file (key_file, group_name, &err);
-  if (!paper_size)
-    {
-      g_propagate_error (error, err);
-      goto out;
-    }
-
-  gtk_page_setup_set_paper_size (setup, paper_size);
-  gtk_paper_size_free (paper_size);
-
-  gtk_page_setup_set_top_margin (setup, top, GTK_UNIT_MM);
-  gtk_page_setup_set_bottom_margin (setup, bottom, GTK_UNIT_MM);
-  gtk_page_setup_set_left_margin (setup, left, GTK_UNIT_MM);
-  gtk_page_setup_set_right_margin (setup, right, GTK_UNIT_MM);
-
-  orientation = g_key_file_get_string (key_file, group_name,
-                                      "Orientation", NULL);
-  if (orientation)
-    {
-      gtk_page_setup_set_orientation (setup,
-                                     string_to_enum (GTK_TYPE_PAGE_ORIENTATION,
-                                                     orientation));
-      g_free (orientation);
-    }
-
-  retval = TRUE;
-
-out:
-  g_free (freeme);
-  return retval;
-}
-
-/**
- * gtk_page_setup_new_from_key_file:
- * @key_file: the `GKeyFile` to retrieve the page_setup from
- * @group_name: (nullable): the name of the group in the key_file to read
- *    to use the default name “Page Setup”
- * @error: (nullable): return location for an error
- *
- * Reads the page setup from the group @group_name in the key file
- * @key_file.
- *
- * Returns a new `GtkPageSetup` object with the restored
- * page setup, or %NULL if an error occurred.
- *
- * Returns: the restored `GtkPageSetup`
- */
-GtkPageSetup *
-gtk_page_setup_new_from_key_file (GKeyFile     *key_file,
-                                 const char   *group_name,
-                                 GError      **error)
-{
-  GtkPageSetup *setup = gtk_page_setup_new ();
-
-  if (!gtk_page_setup_load_key_file (setup, key_file, group_name, error))
-    {
-      g_object_unref (setup);
-      setup = NULL;
-    }
-
-  return setup;
-}
-
-/**
- * gtk_page_setup_to_file:
- * @setup: a `GtkPageSetup`
- * @file_name: (type filename): the file to save to
- * @error: (nullable): return location for errors
- *
- * This function saves the information from @setup to @file_name.
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_page_setup_to_file (GtkPageSetup  *setup,
-                       const char    *file_name,
-                       GError       **error)
-{
-  GKeyFile *key_file;
-  gboolean retval = FALSE;
-  char *data = NULL;
-  gsize len;
-
-  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
-  g_return_val_if_fail (file_name != NULL, FALSE);
-
-  key_file = g_key_file_new ();
-  gtk_page_setup_to_key_file (setup, key_file, NULL);
-
-  data = g_key_file_to_data (key_file, &len, error);
-  if (!data)
-    goto out;
-
-  retval = g_file_set_contents (file_name, data, len, error);
-
-out:
-  g_key_file_free (key_file);
-  g_free (data);
-
-  return retval;
-}
-
-/* something like this should really be in gobject! */
-static char *
-enum_to_string (GType type,
-                guint enum_value)
-{
-  GEnumClass *enum_class;
-  GEnumValue *value;
-  char *retval = NULL;
-
-  enum_class = g_type_class_ref (type);
-
-  value = g_enum_get_value (enum_class, enum_value);
-  if (value)
-    retval = g_strdup (value->value_nick);
-
-  g_type_class_unref (enum_class);
-
-  return retval;
-}
-
-/**
- * gtk_page_setup_to_key_file:
- * @setup: a `GtkPageSetup`
- * @key_file: the `GKeyFile` to save the page setup to
- * @group_name: (nullable): the group to add the settings to in @key_file,
- *   or %NULL to use the default name “Page Setup”
- *
- * This function adds the page setup from @setup to @key_file.
- */
-void
-gtk_page_setup_to_key_file (GtkPageSetup *setup,
-                           GKeyFile     *key_file,
-                           const char   *group_name)
-{
-  GtkPaperSize *paper_size;
-  char *orientation;
-
-  g_return_if_fail (GTK_IS_PAGE_SETUP (setup));
-  g_return_if_fail (key_file != NULL);
-
-  if (!group_name)
-    group_name = KEYFILE_GROUP_NAME;
-
-  paper_size = gtk_page_setup_get_paper_size (setup);
-  g_assert (paper_size != NULL);
-
-  gtk_paper_size_to_key_file (paper_size, key_file, group_name);
-
-  g_key_file_set_double (key_file, group_name,
-                        "MarginTop", gtk_page_setup_get_top_margin (setup, GTK_UNIT_MM));
-  g_key_file_set_double (key_file, group_name,
-                        "MarginBottom", gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_MM));
-  g_key_file_set_double (key_file, group_name,
-                        "MarginLeft", gtk_page_setup_get_left_margin (setup, GTK_UNIT_MM));
-  g_key_file_set_double (key_file, group_name,
-                        "MarginRight", gtk_page_setup_get_right_margin (setup, GTK_UNIT_MM));
-
-  orientation = enum_to_string (GTK_TYPE_PAGE_ORIENTATION,
-                               gtk_page_setup_get_orientation (setup));
-  g_key_file_set_string (key_file, group_name,
-                        "Orientation", orientation);
-  g_free (orientation);
-}
-
-/**
- * gtk_page_setup_to_gvariant:
- * @setup: a `GtkPageSetup`
- *
- * Serialize page setup to an a{sv} variant.
- *
- * Return: (transfer none): a new, floating, `GVariant`
- */
-GVariant *
-gtk_page_setup_to_gvariant (GtkPageSetup *setup)
-{
-  GtkPaperSize *paper_size;
-  GVariant *variant;
-  int i;
-  GVariantBuilder builder;
-  char *orientation;
-
-  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
-
-  paper_size = gtk_page_setup_get_paper_size (setup);
-
-  variant = g_variant_ref_sink (gtk_paper_size_to_gvariant (paper_size));
-  for (i = 0; i < g_variant_n_children (variant); i++)
-    g_variant_builder_add_value (&builder, g_variant_get_child_value (variant, i));
-  g_variant_unref (variant);
-
-  g_variant_builder_add (&builder, "{sv}", "MarginTop", g_variant_new_double (gtk_page_setup_get_top_margin (setup, GTK_UNIT_MM)));
-  g_variant_builder_add (&builder, "{sv}", "MarginBottom", g_variant_new_double (gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_MM)));
-  g_variant_builder_add (&builder, "{sv}", "MarginLeft", g_variant_new_double (gtk_page_setup_get_left_margin (setup, GTK_UNIT_MM)));
-  g_variant_builder_add (&builder, "{sv}", "MarginRight", g_variant_new_double (gtk_page_setup_get_right_margin (setup, GTK_UNIT_MM)));
-
-  orientation = enum_to_string (GTK_TYPE_PAGE_ORIENTATION,
-                                gtk_page_setup_get_orientation (setup));
-  g_variant_builder_add (&builder, "{sv}", "Orientation", g_variant_new_take_string (orientation));
-
-  return g_variant_builder_end (&builder);
-}
-
-/**
- * gtk_page_setup_new_from_gvariant:
- * @variant: an a{sv} `GVariant`
- *
- * Desrialize a page setup from an a{sv} variant.
- *
- * The variant must be in the format produced by
- * [method@Gtk.PageSetup.to_gvariant].
- *
- * Returns: (transfer full): a new `GtkPageSetup` object
- */
-GtkPageSetup *
-gtk_page_setup_new_from_gvariant (GVariant *variant)
-{
-  GtkPageSetup *setup;
-  const char *orientation;
-  double margin;
-  GtkPaperSize *paper_size;
-
-  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
-
-  setup = gtk_page_setup_new ();
-
-  paper_size = gtk_paper_size_new_from_gvariant (variant);
-  if (paper_size)
-    {
-      gtk_page_setup_set_paper_size (setup, paper_size);
-      gtk_paper_size_free (paper_size);
-    }
-
-  if (g_variant_lookup (variant, "MarginTop", "d", &margin))
-    gtk_page_setup_set_top_margin (setup, margin, GTK_UNIT_MM);
-  if (g_variant_lookup (variant, "MarginBottom", "d", &margin))
-    gtk_page_setup_set_bottom_margin (setup, margin, GTK_UNIT_MM);
-  if (g_variant_lookup (variant, "MarginLeft", "d", &margin))
-    gtk_page_setup_set_left_margin (setup, margin, GTK_UNIT_MM);
-  if (g_variant_lookup (variant, "MarginRight", "d", &margin))
-    gtk_page_setup_set_right_margin (setup, margin, GTK_UNIT_MM);
-
-  if (g_variant_lookup (variant, "Orientation", "&s", &orientation))
-    gtk_page_setup_set_orientation (setup, string_to_enum (GTK_TYPE_PAGE_ORIENTATION,
-                                                           orientation));
-
-  return setup;
-}
diff --git a/gtk/gtkpapersize.c b/gtk/gtkpapersize.c
deleted file mode 100644 (file)
index 20fa327..0000000
+++ /dev/null
@@ -1,1118 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkpapersize.c: Paper Size
- * Copyright (C) 2006, Red Hat, Inc.
- * 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 <string.h>
-#include <stdlib.h>
-#include <locale.h>
-#if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
-#include <langinfo.h>
-#endif
-#include <math.h>
-
-#include "print/gtkpapersize.h"
-#include "gtkprintutilsprivate.h"
-#include "print/gtkprintoperation.h"  /* for GtkPrintError */
-#include <glib/gi18n-lib.h>
-
-/* _gtk_load_custom_papers() only on Unix so far  */
-#ifdef G_OS_UNIX
-#include "gtkcustompaperunixdialog.h"
-#endif
-
-#include "paper_names_offsets.c"
-
-
-/**
- * GtkPaperSize:
- *
- * `GtkPaperSize` handles paper sizes.
- *
- * It uses the standard called
- * [PWG 5101.1-2002 PWG: Standard for Media Standardized Names](http://www.pwg.org/standards.html)
- * to name the paper sizes (and to get the data for the page sizes).
- * In addition to standard paper sizes, `GtkPaperSize` allows to
- * construct custom paper sizes with arbitrary dimensions.
- *
- * The `GtkPaperSize` object stores not only the dimensions (width
- * and height) of a paper size and its name, it also provides
- * default print margins.
- */
-
-
-struct _GtkPaperSize
-{
-  const PaperInfo *info;
-
-  /* If these are not set we fall back to info */
-  char *name;
-  char *display_name;
-  char *ppd_name;
-
-  double width, height; /* Stored in mm */
-  gboolean is_custom;
-  gboolean is_ipp;
-};
-
-G_DEFINE_BOXED_TYPE (GtkPaperSize, gtk_paper_size,
-                     gtk_paper_size_copy,
-                     gtk_paper_size_free)
-
-static const PaperInfo *
-lookup_paper_info (const char *name)
-{
-  int lower = 0;
-  int upper = G_N_ELEMENTS (standard_names_offsets) - 1;
-  int mid;
-  int cmp;
-
-  do
-    {
-       mid = (lower + upper) / 2;
-       cmp = strcmp (name, paper_names + standard_names_offsets[mid].name);
-       if (cmp < 0)
-         upper = mid - 1;
-       else if (cmp > 0)
-         lower = mid + 1;
-       else
-         return &standard_names_offsets[mid];
-    }
-  while (lower <= upper);
-
-  return NULL;
-}
-
-static gboolean
-parse_media_size (const char *size,
-                  double      *width_mm,
-                  double      *height_mm)
-{
-  const char *p;
-  char *e;
-  double short_dim, long_dim;
-
-  p = size;
-
-  short_dim = g_ascii_strtod (p, &e);
-
-  if (p == e || *e != 'x')
-    return FALSE;
-
-  p = e + 1; /* Skip x */
-
-  long_dim = g_ascii_strtod (p, &e);
-
-  if (p == e)
-    return FALSE;
-
-  p = e;
-
-  if (strcmp (p, "in") == 0)
-    {
-      short_dim = short_dim * MM_PER_INCH;
-      long_dim = long_dim * MM_PER_INCH;
-    }
-  else if (strcmp (p, "mm") != 0)
-    return FALSE;
-
-  if (width_mm)
-    *width_mm = short_dim;
-  if (height_mm)
-    *height_mm = long_dim;
-
-  return TRUE;
-}
-
-static gboolean
-parse_full_media_size_name (const char   *full_name,
-                            char        **name,
-                            double       *width_mm,
-                            double       *height_mm)
-{
-  const char *p;
-  const char *end_of_name;
-
-  /* From the spec:
-   media-size-self-describing-name =
-        ( class-in "_" size-name "_" short-dim "x" long-dim "in" ) |
-        ( class-mm "_" size-name "_" short-dim "x" long-dim "mm" )
-   class-in = "custom" | "na" | "asme" | "roc" | "oe"
-   class-mm = "custom" | "iso" | "jis" | "jpn" | "prc" | "om"
-   size-name = ( lowalpha | digit ) *( lowalpha | digit | "-" )
-   short-dim = dim
-   long-dim = dim
-   dim = integer-part [fraction-part] | "0" fraction-part
-   integer-part = non-zero-digit *digit
-   fraction-part = "." *digit non-zero-digit
-   lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
-              "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
-              "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
-   non-zero-digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
-   digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
- */
-
-  p = strchr (full_name, '_');
-  if (p == NULL)
-    return FALSE;
-
-  p++; /* Skip _ */
-
-  p = strchr (p, '_');
-  if (p == NULL)
-    return FALSE;
-
-  end_of_name = p;
-
-  p++; /* Skip _ */
-
-  if (!parse_media_size (p, width_mm, height_mm))
-    return FALSE;
-
-  if (name)
-    *name = g_strndup (full_name, end_of_name - full_name);
-
-  return TRUE;
-}
-
-static GtkPaperSize *
-gtk_paper_size_new_from_info (const PaperInfo *info)
-{
-  GtkPaperSize *size;
-
-  size = g_new0 (GtkPaperSize, 1);
-  size->info = info;
-  size->width = info->width;
-  size->height = info->height;
-
-  return size;
-}
-
-/**
- * gtk_paper_size_new:
- * @name: (nullable): a paper size name
- *
- * Creates a new `GtkPaperSize` object by parsing a
- * [PWG 5101.1-2002](ftp://ftp.pwg.org/pub/pwg/candidates/cs-pwgmsn10-20020226-5101.1.pdf)
- * paper name.
- *
- * If @name is %NULL, the default paper size is returned,
- * see [func@Gtk.PaperSize.get_default].
- *
- * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
- * to free it
- */
-GtkPaperSize *
-gtk_paper_size_new (const char *name)
-{
-  GtkPaperSize *size;
-  char *short_name;
-  double width, height;
-  const PaperInfo *info;
-
-  if (name == NULL)
-    name = gtk_paper_size_get_default ();
-
-  if (parse_full_media_size_name (name, &short_name, &width, &height))
-    {
-      info = lookup_paper_info (short_name);
-      if (info != NULL && info->width == width && info->height == height)
-        {
-          size = gtk_paper_size_new_from_info (info);
-          g_free (short_name);
-        }
-      else
-        {
-          size = g_new0 (GtkPaperSize, 1);
-
-          size->width = width;
-          size->height = height;
-          size->name = short_name;
-          size->display_name = g_strdup (short_name);
-          if (strncmp (short_name, "custom", 6) == 0)
-            size->is_custom = TRUE;
-        }
-    }
-  else
-    {
-      info = lookup_paper_info (name);
-      if (info != NULL)
-        size = gtk_paper_size_new_from_info (info);
-      else
-        {
-          g_warning ("Unknown paper size %s", name);
-          size = g_new0 (GtkPaperSize, 1);
-          size->name = g_strdup (name);
-          size->display_name = g_strdup (name);
-          /* Default to A4 size */
-          size->width = 210;
-          size->height = 297;
-        }
-    }
-
-  return size;
-}
-
-static char *
-improve_displayname (const char *name)
-{
-  char *p, *p1, *p2, *s;
-
-  p = strrchr (name, 'x');
-  if (p && p != name &&
-      g_ascii_isdigit (*(p - 1)) &&
-      g_ascii_isdigit (*(p + 1)))
-    {
-      p1 = g_strndup (name, p - name);
-      p2 = g_strdup (p + 1);
-      s = g_strconcat (p1, "×", p2, NULL);
-      g_free (p1);
-      g_free (p2);
-    }
-  else
-    s = g_strdup (name);
-
-  return s;
-}
-
-/**
- * gtk_paper_size_new_from_ppd:
- * @ppd_name: a PPD paper name
- * @ppd_display_name: the corresponding human-readable name
- * @width: the paper width, in points
- * @height: the paper height in points
- *
- * Creates a new `GtkPaperSize` object by using
- * PPD information.
- *
- * If @ppd_name is not a recognized PPD paper name,
- * @ppd_display_name, @width and @height are used to
- * construct a custom `GtkPaperSize` object.
- *
- * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
- * to free it
- */
-GtkPaperSize *
-gtk_paper_size_new_from_ppd (const char *ppd_name,
-                             const char *ppd_display_name,
-                             double       width,
-                             double       height)
-{
-  char *name;
-  const char *lookup_ppd_name;
-  char *freeme;
-  GtkPaperSize *size;
-  int i;
-  char *display_name;
-
-  lookup_ppd_name = ppd_name;
-
-  freeme = NULL;
-  /* Strip out Traverse suffix in matching. */
-  if (g_str_has_suffix (ppd_name, ".Transverse"))
-    {
-      lookup_ppd_name = freeme =
-        g_strndup (ppd_name, strlen (ppd_name) - strlen (".Transverse"));
-    }
-
-  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
-    {
-      if (standard_names_offsets[i].ppd_name != -1 &&
-          strcmp (paper_names + standard_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
-        {
-          size = gtk_paper_size_new_from_info (&standard_names_offsets[i]);
-          goto out;
-        }
-    }
-
-  for (i = 0; i < G_N_ELEMENTS (extra_ppd_names_offsets); i++)
-    {
-      if (strcmp (paper_names + extra_ppd_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
-        {
-          size = gtk_paper_size_new (paper_names + extra_ppd_names_offsets[i].standard_name);
-          goto out;
-        }
-    }
-
-  name = g_strconcat ("ppd_", ppd_name, NULL);
-  display_name = improve_displayname (ppd_display_name);
-  size = gtk_paper_size_new_custom (name, display_name, width, height, GTK_UNIT_POINTS);
-  g_free (display_name);
-  g_free (name);
-
- out:
-
-  if (size->info == NULL ||
-      size->info->ppd_name == -1 ||
-      strcmp (paper_names + size->info->ppd_name, ppd_name) != 0)
-    size->ppd_name = g_strdup (ppd_name);
-
-  g_free (freeme);
-
-  return size;
-}
-
-/* Tolerance of paper size in points according to PostScript Language Reference */
-#define PAPER_SIZE_TOLERANCE 5
-
-/**
- * gtk_paper_size_new_from_ipp:
- * @ipp_name: an IPP paper name
- * @width: the paper width, in points
- * @height: the paper height in points
- *
- * Creates a new `GtkPaperSize` object by using
- * IPP information.
- *
- * If @ipp_name is not a recognized paper name,
- * @width and @height are used to
- * construct a custom `GtkPaperSize` object.
- *
- * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
- * to free it
- */
-GtkPaperSize *
-gtk_paper_size_new_from_ipp (const char *ipp_name,
-                             double       width,
-                             double       height)
-{
-  GtkPaperSize *size;
-  const char   *name = NULL;
-  gboolean      found = FALSE;
-  float         x_dimension;
-  float         y_dimension;
-  char         *display_name = NULL;
-  int           i;
-
-  /* Find paper size according to its name */
-  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
-    {
-      if (standard_names_offsets[i].name != -1)
-        name = paper_names + standard_names_offsets[i].name;
-      if (name != NULL &&
-          /* Given paper size name is equal to a name
-             from the standard paper size names list. */
-          ((g_strcmp0 (ipp_name, name) == 0) ||
-           /* Given paper size name is prefixed by a name
-              from the standard paper size names list +
-              it consists of size in its name (e.g. iso_a4_210x297mm). */
-            (g_str_has_prefix (ipp_name, name) &&
-             strlen (ipp_name) > strlen (name) + 2 &&
-             ipp_name[strlen (ipp_name)] == '_' &&
-             g_ascii_isdigit (ipp_name[strlen (ipp_name) + 1]) &&
-             (g_str_has_suffix (ipp_name, "mm") ||
-              g_str_has_suffix (ipp_name, "in")))))
-        {
-          display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,
-                                                 "paper size",
-                                                 paper_names + standard_names_offsets[i].display_name));
-          found = TRUE;
-          break;
-        }
-    }
-
-  /* Find paper size according to its size */
-  if (display_name == NULL)
-    {
-      for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
-        {
-          x_dimension = _gtk_print_convert_from_mm (standard_names_offsets[i].width, GTK_UNIT_POINTS);
-          y_dimension = _gtk_print_convert_from_mm (standard_names_offsets[i].height, GTK_UNIT_POINTS);
-
-          if (fabs (x_dimension - width) <= PAPER_SIZE_TOLERANCE &&
-              fabs (y_dimension - height) <= PAPER_SIZE_TOLERANCE)
-            {
-              display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,
-                                                     "paper size",
-                                                     paper_names + standard_names_offsets[i].display_name));
-              found = TRUE;
-              break;
-            }
-        }
-    }
-
-  /* Fallback to name of the paper size as given in "ipp_name" parameter */
-  if (display_name == NULL)
-    display_name = g_strdup (ipp_name);
-
-  size = gtk_paper_size_new_custom (ipp_name, display_name, width, height, GTK_UNIT_POINTS);
-  size->is_custom = !found;
-  size->is_ipp = found;
-
-  g_free (display_name);
-
-  return size;
-}
-
-/**
- * gtk_paper_size_new_custom:
- * @name: the paper name
- * @display_name: the human-readable name
- * @width: the paper width, in units of @unit
- * @height: the paper height, in units of @unit
- * @unit: the unit for @width and @height. not %GTK_UNIT_NONE.
- *
- * Creates a new `GtkPaperSize` object with the
- * given parameters.
- *
- * Returns: a new `GtkPaperSize` object, use [method@Gtk.PaperSize.free]
- * to free it
- */
-GtkPaperSize *
-gtk_paper_size_new_custom (const char *name,
-                           const char *display_name,
-                           double       width,
-                           double       height,
-                           GtkUnit      unit)
-{
-  GtkPaperSize *size;
-  g_return_val_if_fail (name != NULL, NULL);
-  g_return_val_if_fail (unit != GTK_UNIT_NONE, NULL);
-
-  size = g_new0 (GtkPaperSize, 1);
-
-  size->name = g_strdup (name);
-  size->display_name = g_strdup (display_name);
-  size->is_custom = TRUE;
-
-  size->width = _gtk_print_convert_to_mm (width, unit);
-  size->height = _gtk_print_convert_to_mm (height, unit);
-
-  return size;
-}
-
-/**
- * gtk_paper_size_copy:
- * @other: a `GtkPaperSize`
- *
- * Copies an existing `GtkPaperSize`.
- *
- * Returns: a copy of @other
- */
-GtkPaperSize *
-gtk_paper_size_copy (GtkPaperSize *other)
-{
-  GtkPaperSize *size;
-
-  size = g_new0 (GtkPaperSize, 1);
-
-  size->info = other->info;
-  if (other->name)
-    size->name = g_strdup (other->name);
-  if (other->display_name)
-    size->display_name = g_strdup (other->display_name);
-  if (other->ppd_name)
-    size->ppd_name = g_strdup (other->ppd_name);
-
-  size->width = other->width;
-  size->height = other->height;
-  size->is_custom = other->is_custom;
-  size->is_ipp = other->is_ipp;
-
-  return size;
-}
-
-/**
- * gtk_paper_size_free:
- * @size: a `GtkPaperSize`
- *
- * Free the given `GtkPaperSize` object.
- */
-void
-gtk_paper_size_free (GtkPaperSize *size)
-{
-  g_free (size->name);
-  g_free (size->display_name);
-  g_free (size->ppd_name);
-  g_free (size);
-}
-
-/**
- * gtk_paper_size_is_equal:
- * @size1: a `GtkPaperSize` object
- * @size2: another `GtkPaperSize` object
- *
- * Compares two `GtkPaperSize` objects.
- *
- * Returns: %TRUE, if @size1 and @size2
- * represent the same paper size
- */
-gboolean
-gtk_paper_size_is_equal (GtkPaperSize *size1,
-                         GtkPaperSize *size2)
-{
-  if (size1->info != NULL && size2->info != NULL)
-    return size1->info == size2->info;
-
-  return strcmp (gtk_paper_size_get_name (size1),
-                 gtk_paper_size_get_name (size2)) == 0;
-}
-
-/**
- * gtk_paper_size_get_paper_sizes:
- * @include_custom: whether to include custom paper sizes
- *   as defined in the page setup dialog
- *
- * Creates a list of known paper sizes.
- *
- * Returns:  (element-type GtkPaperSize) (transfer full): a newly allocated list of newly
- *    allocated `GtkPaperSize` objects
- */
-GList *
-gtk_paper_size_get_paper_sizes (gboolean include_custom)
-{
-  GList *list = NULL;
-  guint i;
-/* _gtk_load_custom_papers() only on Unix so far  */
-#ifdef G_OS_UNIX
-  if (include_custom)
-    {
-      GList *page_setups, *l;
-
-      page_setups = _gtk_load_custom_papers ();
-      for (l = page_setups; l != NULL; l = l->next)
-        {
-          GtkPageSetup *setup = (GtkPageSetup *) l->data;
-          GtkPaperSize *size;
-
-          size = gtk_page_setup_get_paper_size (setup);
-          list = g_list_prepend (list, gtk_paper_size_copy (size));
-        }
-
-      g_list_free_full (page_setups, g_object_unref);
-    }
-#endif
-  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); ++i)
-    {
-       GtkPaperSize *size;
-
-       size = gtk_paper_size_new_from_info (&standard_names_offsets[i]);
-       list = g_list_prepend (list, size);
-    }
-
-  return g_list_reverse (list);
-}
-
-
-/**
- * gtk_paper_size_get_name:
- * @size: a `GtkPaperSize` object
- *
- * Gets the name of the `GtkPaperSize`.
- *
- * Returns: the name of @size
- */
-const char *
-gtk_paper_size_get_name (GtkPaperSize *size)
-{
-  if (size->name)
-    return size->name;
-  g_assert (size->info != NULL);
-  return paper_names + size->info->name;
-}
-
-/**
- * gtk_paper_size_get_display_name:
- * @size: a `GtkPaperSize` object
- *
- * Gets the human-readable name of the `GtkPaperSize`.
- *
- * Returns: the human-readable name of @size
- */
-const char *
-gtk_paper_size_get_display_name (GtkPaperSize *size)
-{
-  const char *display_name;
-
-  if (size->display_name)
-    return size->display_name;
-
-  g_assert (size->info != NULL);
-
-  display_name = paper_names + size->info->display_name;
-  return g_dpgettext2 (GETTEXT_PACKAGE, "paper size", display_name);
-}
-
-/**
- * gtk_paper_size_get_ppd_name:
- * @size: a `GtkPaperSize` object
- *
- * Gets the PPD name of the `GtkPaperSize`, which
- * may be %NULL.
- *
- * Returns: the PPD name of @size
- */
-const char *
-gtk_paper_size_get_ppd_name (GtkPaperSize *size)
-{
-  if (size->ppd_name)
-    return size->ppd_name;
-  if (size->info)
-    return paper_names + size->info->ppd_name;
-  return NULL;
-}
-
-/**
- * gtk_paper_size_get_width:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the paper width of the `GtkPaperSize`, in
- * units of @unit.
- *
- * Returns: the paper width
- */
-double
-gtk_paper_size_get_width (GtkPaperSize *size,
-                          GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (size->width, unit);
-}
-
-/**
- * gtk_paper_size_get_height:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the paper height of the `GtkPaperSize`, in
- * units of @unit.
- *
- * Returns: the paper height
- */
-double
-gtk_paper_size_get_height (GtkPaperSize *size,
-                           GtkUnit       unit)
-{
-  return _gtk_print_convert_from_mm (size->height, unit);
-}
-
-/**
- * gtk_paper_size_is_custom:
- * @size: a `GtkPaperSize` object
- *
- * Returns %TRUE if @size is not a standard paper size.
- *
- * Returns: whether @size is a custom paper size.
- **/
-gboolean
-gtk_paper_size_is_custom (GtkPaperSize *size)
-{
-  return size->is_custom;
-}
-
-/**
- * gtk_paper_size_is_ipp:
- * @size: a `GtkPaperSize` object
- *
- * Returns %TRUE if @size is an IPP standard paper size.
- *
- * Returns: whether @size is not an IPP custom paper size.
- **/
-gboolean
-gtk_paper_size_is_ipp (GtkPaperSize *size)
-{
-  return size->is_ipp;
-}
-
-/**
- * gtk_paper_size_set_size:
- * @size: a custom `GtkPaperSize` object
- * @width: the new width in units of @unit
- * @height: the new height in units of @unit
- * @unit: the unit for @width and @height
- *
- * Changes the dimensions of a @size to @width x @height.
- */
-void
-gtk_paper_size_set_size (GtkPaperSize *size,
-                         double        width,
-                         double        height,
-                         GtkUnit       unit)
-{
-  g_return_if_fail (size != NULL);
-  g_return_if_fail (size->is_custom);
-
-  size->width = _gtk_print_convert_to_mm (width, unit);
-  size->height = _gtk_print_convert_to_mm (height, unit);
-}
-
-#define NL_PAPER_GET(x)         \
-  ((union { char *string; unsigned int word; })nl_langinfo(x)).word
-
-/**
- * gtk_paper_size_get_default:
- *
- * Returns the name of the default paper size, which
- * depends on the current locale.
- *
- * Returns: the name of the default paper size. The string
- * is owned by GTK and should not be modified.
- */
-const char *
-gtk_paper_size_get_default (void)
-{
-  char *locale, *freeme = NULL;
-  const char *paper_size;
-
-#if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
-  {
-    int width = NL_PAPER_GET (_NL_PAPER_WIDTH);
-    int height = NL_PAPER_GET (_NL_PAPER_HEIGHT);
-
-    if (width == 210 && height == 297)
-      return GTK_PAPER_NAME_A4;
-
-    if (width == 216 && height == 279)
-      return GTK_PAPER_NAME_LETTER;
-  }
-#endif
-
-#ifdef G_OS_WIN32
-  freeme = locale = g_win32_getlocale ();
-#elif defined(LC_PAPER)
-  locale = setlocale(LC_PAPER, NULL);
-#else
-  locale = setlocale(LC_MESSAGES, NULL);
-#endif
-
-  if (!locale)
-    return GTK_PAPER_NAME_A4;
-
-  /* CLDR 1.8.1
-   * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/territory_language_information.html
-   */
-  if (g_regex_match_simple("[^_.@]{2,3}_(BZ|CA|CL|CO|CR|GT|MX|NI|PA|PH|PR|SV|US|VE)",
-                           locale, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED))
-    paper_size = GTK_PAPER_NAME_LETTER;
-  else
-    paper_size = GTK_PAPER_NAME_A4;
-
-  g_free (freeme);
-  return paper_size;
-}
-
-/* These get the default margins used for the paper size. Its
- * larger than most printers margins, so that it will be within
- * the imageble area on any printer.
- *
- * I’ve taken the actual values used from the OSX page setup dialog.
- * I’m not sure exactly where they got these values for, but might
- * correspond to this (from ghostscript docs):
- *
- * All DeskJets have 0.5 inches (1.27cm) of unprintable bottom margin,
- * due to the mechanical arrangement used to grab the paper. Side margins
- * are approximately 0.25 inches (0.64cm) for U.S. letter paper, and 0.15
- * inches (0.38cm) for A4.
- */
-
-/**
- * gtk_paper_size_get_default_top_margin:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the default top margin for the `GtkPaperSize`.
- *
- * Returns: the default top margin
- */
-double
-gtk_paper_size_get_default_top_margin (GtkPaperSize *size,
-                                       GtkUnit       unit)
-{
-  double margin;
-
-  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
-  return _gtk_print_convert_from_mm (margin, unit);
-}
-
-/**
- * gtk_paper_size_get_default_bottom_margin:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the default bottom margin for the `GtkPaperSize`.
- *
- * Returns: the default bottom margin
- */
-double
-gtk_paper_size_get_default_bottom_margin (GtkPaperSize *size,
-                                          GtkUnit       unit)
-{
-  double margin;
-  const char *name;
-
-  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
-
-  name = gtk_paper_size_get_name (size);
-  if (strcmp (name, "na_letter") == 0 ||
-      strcmp (name, "na_legal") == 0 ||
-      strcmp (name, "iso_a4") == 0)
-    margin = _gtk_print_convert_to_mm (0.56, GTK_UNIT_INCH);
-
-  return _gtk_print_convert_from_mm (margin, unit);
-}
-
-/**
- * gtk_paper_size_get_default_left_margin:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the default left margin for the `GtkPaperSize`.
- *
- * Returns: the default left margin
- */
-double
-gtk_paper_size_get_default_left_margin (GtkPaperSize *size,
-                                        GtkUnit       unit)
-{
-  double margin;
-
-  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
-  return _gtk_print_convert_from_mm (margin, unit);
-}
-
-/**
- * gtk_paper_size_get_default_right_margin:
- * @size: a `GtkPaperSize` object
- * @unit: the unit for the return value, not %GTK_UNIT_NONE
- *
- * Gets the default right margin for the `GtkPaperSize`.
- *
- * Returns: the default right margin
- */
-double
-gtk_paper_size_get_default_right_margin (GtkPaperSize *size,
-                                         GtkUnit       unit)
-{
-  double margin;
-
-  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
-  return _gtk_print_convert_from_mm (margin, unit);
-}
-
-/**
- * gtk_paper_size_new_from_key_file:
- * @key_file: the `GKeyFile` to retrieve the papersize from
- * @group_name: (nullable): the name of the group in the key file to read,
- *   or %NULL to read the first group
- * @error: (nullable): return location for an error
- *
- * Reads a paper size from the group @group_name in the key file
- * @key_file.
- *
- * Returns: a new `GtkPaperSize` object with the restored paper size
- */
-GtkPaperSize *
-gtk_paper_size_new_from_key_file (GKeyFile     *key_file,
-                                  const char   *group_name,
-                                  GError      **error)
-{
-  GtkPaperSize *paper_size = NULL;
-  char *name = NULL;
-  char *ppd_name = NULL;
-  char *display_name = NULL;
-  char *freeme = NULL;
-  double width, height;
-  GError *err = NULL;
-
-  g_return_val_if_fail (key_file != NULL, NULL);
-
-  if (!group_name)
-    group_name = freeme = g_key_file_get_start_group (key_file);
-  if (!group_name || !g_key_file_has_group (key_file, group_name))
-    {
-      g_set_error_literal (error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_INVALID_FILE,
-                           _("Not a valid page setup file"));
-      goto out;
-    }
-
-#define GET_DOUBLE(kf, group, name, v) \
-  v = g_key_file_get_double (kf, group, name, &err); \
-  if (err != NULL) \
-    {\
-      g_propagate_error (error, err);\
-      goto out;\
-    }
-
-  GET_DOUBLE (key_file, group_name, "Width", width);
-  GET_DOUBLE (key_file, group_name, "Height", height);
-
-#undef GET_DOUBLE
-
-  name = g_key_file_get_string (key_file, group_name,
-                                "Name", NULL);
-  ppd_name = g_key_file_get_string (key_file, group_name,
-                                    "PPDName", NULL);
-  display_name = g_key_file_get_string (key_file, group_name,
-                                        "DisplayName", NULL);
-  /* Fallback for old ~/.gtk-custom-paper entries */
-  if (!display_name)
-    display_name = g_strdup (name);
-
-  if (ppd_name != NULL)
-    paper_size = gtk_paper_size_new_from_ppd (ppd_name,
-                                              display_name,
-                                              _gtk_print_convert_from_mm (width, GTK_UNIT_POINTS),
-                                              _gtk_print_convert_from_mm (height, GTK_UNIT_POINTS));
-  else if (name != NULL)
-    paper_size = gtk_paper_size_new_custom (name, display_name,
-                                            width, height, GTK_UNIT_MM);
-  else
-    {
-      g_set_error_literal (error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_INVALID_FILE,
-                           _("Not a valid page setup file"));
-      goto out;
-    }
-
-  g_assert (paper_size != NULL);
-
-out:
-  g_free (ppd_name);
-  g_free (name);
-  g_free (display_name);
-  g_free (freeme);
-
-  return paper_size;
-}
-
-/**
- * gtk_paper_size_to_key_file:
- * @size: a `GtkPaperSize`
- * @key_file: the `GKeyFile` to save the paper size to
- * @group_name: the group to add the settings to in @key_file
- *
- * This function adds the paper size from @size to @key_file.
- */
-void
-gtk_paper_size_to_key_file (GtkPaperSize *size,
-                            GKeyFile     *key_file,
-                            const char   *group_name)
-{
-  const char *name, *ppd_name, *display_name;
-
-  g_return_if_fail (size != NULL);
-  g_return_if_fail (key_file != NULL);
-
-  name = gtk_paper_size_get_name (size);
-  display_name = gtk_paper_size_get_display_name (size);
-  ppd_name = gtk_paper_size_get_ppd_name (size);
-
-  if (ppd_name != NULL)
-    g_key_file_set_string (key_file, group_name,
-                           "PPDName", ppd_name);
-  else
-    g_key_file_set_string (key_file, group_name,
-                           "Name", name);
-
-  if (display_name)
-    g_key_file_set_string (key_file, group_name,
-                           "DisplayName", display_name);
-
-  g_key_file_set_double (key_file, group_name,
-                         "Width", gtk_paper_size_get_width (size, GTK_UNIT_MM));
-  g_key_file_set_double (key_file, group_name,
-                         "Height", gtk_paper_size_get_height (size, GTK_UNIT_MM));
-}
-
-/**
- * gtk_paper_size_to_gvariant:
- * @paper_size: a `GtkPaperSize`
- *
- * Serialize a paper size to an `a{sv}` variant.
- *
- * Returns: (transfer none): a new, floating, `GVariant`
- */
-GVariant *
-gtk_paper_size_to_gvariant (GtkPaperSize *paper_size)
-{
-  const char *name;
-  const char *ppd_name;
-  const char *display_name;
-  GVariantBuilder builder;
-
-  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
-
-  name = gtk_paper_size_get_name (paper_size);
-  ppd_name = gtk_paper_size_get_ppd_name (paper_size);
-  display_name = gtk_paper_size_get_display_name (paper_size);
-
-  if (ppd_name != NULL)
-    g_variant_builder_add (&builder, "{sv}", "PPDName", g_variant_new_string (ppd_name));
-  else
-    g_variant_builder_add (&builder, "{sv}", "Name", g_variant_new_string (name));
-
-  if (display_name != NULL)
-    g_variant_builder_add (&builder, "{sv}", "DisplayName", g_variant_new_string (display_name));
-
-  g_variant_builder_add (&builder, "{sv}", "Width", g_variant_new_double (gtk_paper_size_get_width (paper_size, GTK_UNIT_MM)));
-  g_variant_builder_add (&builder, "{sv}", "Height", g_variant_new_double (gtk_paper_size_get_height (paper_size, GTK_UNIT_MM)));
-
-  return g_variant_builder_end (&builder);
-}
-
-/**
- * gtk_paper_size_new_from_gvariant:
- * @variant: an a{sv} `GVariant`
- *
- * Deserialize a paper size from a `GVariant`.
- *
- * The `GVariant must be in the format produced by
- * [method@Gtk.PaperSize.to_gvariant].
- *
- * Returns: (transfer full): a new `GtkPaperSize` object
- */
-GtkPaperSize *
-gtk_paper_size_new_from_gvariant (GVariant *variant)
-{
-  GtkPaperSize *paper_size;
-  const char *name;
-  const char *ppd_name;
-  const char *display_name;
-  double width, height;
-
-  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
-
-  if (!g_variant_lookup (variant, "Width", "d", &width) ||
-      !g_variant_lookup (variant, "Height", "d", &height))
-    return NULL;
-
-  if (!g_variant_lookup (variant, "Name", "&s", &name))
-    name = NULL;
-
-  if (!g_variant_lookup (variant, "PPDName", "&s", &ppd_name))
-    ppd_name = NULL;
-
-  if (!g_variant_lookup (variant, "DisplayName", "&s", &display_name))
-    display_name = name;
-
-  if (ppd_name != NULL)
-    paper_size = gtk_paper_size_new_from_ppd (ppd_name,
-                                              display_name,
-                                              _gtk_print_convert_from_mm (width, GTK_UNIT_POINTS),
-                                              _gtk_print_convert_from_mm (height, GTK_UNIT_POINTS));
-  else if (name != NULL)
-    paper_size = gtk_paper_size_new_custom (name, display_name,
-                                            width, height, GTK_UNIT_MM);
-  else
-    paper_size = NULL;
-
-  return paper_size;
-}
diff --git a/gtk/gtkprintcontext.c b/gtk/gtkprintcontext.c
deleted file mode 100644 (file)
index 1141062..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkprintcontext.c: Print Context
- * 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 "gtkprintoperation-private.h"
-
-
-/**
- * GtkPrintContext:
- *
- * A `GtkPrintContext` encapsulates context information that is required when
- * drawing pages for printing.
- *
- * This includes the cairo context and important parameters like page size
- * and resolution. It also lets you easily create [class@Pango.Layout] and
- * [class@Pango.Context] objects that match the font metrics of the cairo surface.
- *
- * `GtkPrintContext` objects get passed to the
- * [signal@Gtk.PrintOperation::begin-print],
- * [signal@Gtk.PrintOperation::end-print],
- * [signal@Gtk.PrintOperation::request-page-setup] and
- * [signal@Gtk.PrintOperation::draw-page] signals on the
- * [class@Gtk.PrintOperation] object.
- *
- * ## Using GtkPrintContext in a ::draw-page callback
- *
- * ```c
- * static void
- * draw_page (GtkPrintOperation *operation,
- *            GtkPrintContext   *context,
- *            int                page_nr)
- * {
- *   cairo_t *cr;
- *   PangoLayout *layout;
- *   PangoFontDescription *desc;
- *
- *   cr = gtk_print_context_get_cairo_context (context);
- *
- *   // Draw a red rectangle, as wide as the paper (inside the margins)
- *   cairo_set_source_rgb (cr, 1.0, 0, 0);
- *   cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
- *
- *   cairo_fill (cr);
- *
- *   // Draw some lines
- *   cairo_move_to (cr, 20, 10);
- *   cairo_line_to (cr, 40, 20);
- *   cairo_arc (cr, 60, 60, 20, 0, M_PI);
- *   cairo_line_to (cr, 80, 20);
- *
- *   cairo_set_source_rgb (cr, 0, 0, 0);
- *   cairo_set_line_width (cr, 5);
- *   cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
- *   cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
- *
- *   cairo_stroke (cr);
- *
- *   // Draw some text
- *   layout = gtk_print_context_create_pango_layout (context);
- *   pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
- *   desc = pango_font_description_from_string ("sans 28");
- *   pango_layout_set_font_description (layout, desc);
- *   pango_font_description_free (desc);
- *
- *   cairo_move_to (cr, 30, 20);
- *   pango_cairo_layout_path (cr, layout);
- *
- *   // Font Outline
- *   cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
- *   cairo_set_line_width (cr, 0.5);
- *   cairo_stroke_preserve (cr);
- *
- *   // Font Fill
- *   cairo_set_source_rgb (cr, 0, 0.0, 1.0);
- *   cairo_fill (cr);
- *
- *   g_object_unref (layout);
- * }
- * ```
- */
-
-
-typedef struct _GtkPrintContextClass GtkPrintContextClass;
-
-#define GTK_IS_PRINT_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_CONTEXT))
-#define GTK_PRINT_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
-#define GTK_PRINT_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
-
-#define MM_PER_INCH 25.4
-#define POINTS_PER_INCH 72
-
-struct _GtkPrintContext
-{
-  GObject parent_instance;
-
-  GtkPrintOperation *op;
-  cairo_t *cr;
-  GtkPageSetup *page_setup;
-
-  double surface_dpi_x;
-  double surface_dpi_y;
-  
-  double pixels_per_unit_x;
-  double pixels_per_unit_y;
-
-  gboolean has_hard_margins;
-  double hard_margin_top;
-  double hard_margin_bottom;
-  double hard_margin_left;
-  double hard_margin_right;
-
-};
-
-struct _GtkPrintContextClass
-{
-  GObjectClass parent_class;
-};
-
-G_DEFINE_TYPE (GtkPrintContext, gtk_print_context, G_TYPE_OBJECT)
-
-static void
-gtk_print_context_finalize (GObject *object)
-{
-  GtkPrintContext *context = GTK_PRINT_CONTEXT (object);
-
-  if (context->page_setup)
-    g_object_unref (context->page_setup);
-
-  if (context->cr)
-    cairo_destroy (context->cr);
-  
-  G_OBJECT_CLASS (gtk_print_context_parent_class)->finalize (object);
-}
-
-static void
-gtk_print_context_init (GtkPrintContext *context)
-{
-}
-
-static void
-gtk_print_context_class_init (GtkPrintContextClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->finalize = gtk_print_context_finalize;
-}
-
-
-GtkPrintContext *
-_gtk_print_context_new (GtkPrintOperation *op)
-{
-  GtkPrintContext *context;
-
-  context = g_object_new (GTK_TYPE_PRINT_CONTEXT, NULL);
-
-  context->op = op;
-  context->cr = NULL;
-  context->has_hard_margins = FALSE;
-  
-  return context;
-}
-
-static PangoFontMap *
-_gtk_print_context_get_fontmap (GtkPrintContext *context)
-{
-  return pango_cairo_font_map_get_default ();
-}
-
-/**
- * gtk_print_context_set_cairo_context:
- * @context: a `GtkPrintContext`
- * @cr: the cairo context
- * @dpi_x: the horizontal resolution to use with @cr
- * @dpi_y: the vertical resolution to use with @cr
- *
- * Sets a new cairo context on a print context.
- *
- * This function is intended to be used when implementing
- * an internal print preview, it is not needed for printing,
- * since GTK itself creates a suitable cairo context in that
- * case.
- */
-void
-gtk_print_context_set_cairo_context (GtkPrintContext *context,
-                                    cairo_t         *cr,
-                                    double           dpi_x,
-                                    double           dpi_y)
-{
-  if (context->cr)
-    cairo_destroy (context->cr);
-
-  context->cr = cairo_reference (cr);
-  context->surface_dpi_x = dpi_x;
-  context->surface_dpi_y = dpi_y;
-
-  switch (context->op->priv->unit)
-    {
-    default:
-    case GTK_UNIT_NONE:
-      /* Do nothing, this is the cairo default unit */
-      context->pixels_per_unit_x = 1.0;
-      context->pixels_per_unit_y = 1.0;
-      break;
-    case GTK_UNIT_POINTS:
-      context->pixels_per_unit_x = dpi_x / POINTS_PER_INCH;
-      context->pixels_per_unit_y = dpi_y / POINTS_PER_INCH;
-      break;
-    case GTK_UNIT_INCH:
-      context->pixels_per_unit_x = dpi_x;
-      context->pixels_per_unit_y = dpi_y;
-      break;
-    case GTK_UNIT_MM:
-      context->pixels_per_unit_x = dpi_x / MM_PER_INCH;
-      context->pixels_per_unit_y = dpi_y / MM_PER_INCH;
-      break;
-    }
-  cairo_scale (context->cr,
-              context->pixels_per_unit_x,
-              context->pixels_per_unit_y);
-}
-
-
-void
-_gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context)
-{
-  cairo_t *cr = context->cr;
-  cairo_matrix_t matrix;
-  GtkPaperSize *paper_size;
-  double width, height;
-
-  paper_size = gtk_page_setup_get_paper_size (context->page_setup);
-
-  width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
-  width = width * context->surface_dpi_x / context->pixels_per_unit_x;
-  height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
-  height = height * context->surface_dpi_y / context->pixels_per_unit_y;
-  
-  switch (gtk_page_setup_get_orientation (context->page_setup))
-    {
-    default:
-    case GTK_PAGE_ORIENTATION_PORTRAIT:
-      break;
-    case GTK_PAGE_ORIENTATION_LANDSCAPE:
-      cairo_translate (cr, 0, height);
-      cairo_matrix_init (&matrix,
-                        0, -1,
-                        1,  0,
-                        0,  0);
-      cairo_transform (cr, &matrix);
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-      cairo_translate (cr, width, height);
-      cairo_matrix_init (&matrix,
-                        -1,  0,
-                         0, -1,
-                         0,  0);
-      cairo_transform (cr, &matrix);
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-      cairo_translate (cr, width, 0);
-      cairo_matrix_init (&matrix,
-                         0,  1,
-                        -1,  0,
-                         0,  0);
-      cairo_transform (cr, &matrix);
-      break;
-    }
-}
-
-void
-_gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context)
-{
-  cairo_t *cr = context->cr;
-  cairo_matrix_t matrix;
-  double width, height;
-
-  width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
-  width = width * context->surface_dpi_x / context->pixels_per_unit_x;
-  height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
-  height = height * context->surface_dpi_y / context->pixels_per_unit_y;
-
-  switch (gtk_page_setup_get_orientation (context->page_setup))
-    {
-    default:
-    case GTK_PAGE_ORIENTATION_PORTRAIT:
-    case GTK_PAGE_ORIENTATION_LANDSCAPE:
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-      cairo_translate (cr, width, height);
-      cairo_matrix_init (&matrix,
-                        -1,  0,
-                         0, -1,
-                         0,  0);
-      cairo_transform (cr, &matrix);
-      break;
-    }
-}
-
-void
-_gtk_print_context_translate_into_margin (GtkPrintContext *context)
-{
-  double dx, dy;
-
-  g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
-
-  /* We do it this way to also handle GTK_UNIT_NONE */
-  switch (gtk_page_setup_get_orientation (context->page_setup))
-    {
-      default:
-      case GTK_PAGE_ORIENTATION_PORTRAIT:
-        dx = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
-        dy = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
-        break;
-      case GTK_PAGE_ORIENTATION_LANDSCAPE:
-        dx = gtk_page_setup_get_bottom_margin (context->page_setup, GTK_UNIT_INCH);
-        dy = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
-        break;
-      case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-        dx = gtk_page_setup_get_right_margin (context->page_setup, GTK_UNIT_INCH);
-        dy = gtk_page_setup_get_bottom_margin (context->page_setup, GTK_UNIT_INCH);
-        break;
-      case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-        dx = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
-        dy = gtk_page_setup_get_right_margin (context->page_setup, GTK_UNIT_INCH);
-        break;
-    }
-
-  cairo_translate (context->cr,
-                   dx * context->surface_dpi_x / context->pixels_per_unit_x,
-                   dy * context->surface_dpi_y / context->pixels_per_unit_y);
-}
-
-void
-_gtk_print_context_set_page_setup (GtkPrintContext *context,
-                                  GtkPageSetup    *page_setup)
-{
-  g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
-  g_return_if_fail (page_setup == NULL ||
-                   GTK_IS_PAGE_SETUP (page_setup));
-
-  if (page_setup != NULL)
-    g_object_ref (page_setup);
-
-  if (context->page_setup != NULL)
-    g_object_unref (context->page_setup);
-
-  context->page_setup = page_setup;
-}
-
-/**
- * gtk_print_context_get_cairo_context:
- * @context: a `GtkPrintContext`
- *
- * Obtains the cairo context that is associated with the
- * `GtkPrintContext`.
- *
- * Returns: (transfer none): the cairo context of @context
- */
-cairo_t *
-gtk_print_context_get_cairo_context (GtkPrintContext *context)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
-
-  return context->cr;
-}
-
-/**
- * gtk_print_context_get_page_setup:
- * @context: a `GtkPrintContext`
- *
- * Obtains the `GtkPageSetup` that determines the page
- * dimensions of the `GtkPrintContext`.
- *
- * Returns: (transfer none): the page setup of @context
- */
-GtkPageSetup *
-gtk_print_context_get_page_setup (GtkPrintContext *context)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
-
-  return context->page_setup;
-}
-
-/**
- * gtk_print_context_get_width:
- * @context: a `GtkPrintContext`
- *
- * Obtains the width of the `GtkPrintContext`, in pixels.
- *
- * Returns: the width of @context
- */
-double
-gtk_print_context_get_width (GtkPrintContext *context)
-{
-  GtkPrintOperationPrivate *priv;
-  double width;
-
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
-
-  priv = context->op->priv;
-
-  if (priv->use_full_page)
-    width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
-  else
-    width = gtk_page_setup_get_page_width (context->page_setup, GTK_UNIT_INCH);
-
-  /* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
-  return width * context->surface_dpi_x / context->pixels_per_unit_x;
-}
-
-/**
- * gtk_print_context_get_height:
- * @context: a `GtkPrintContext`
- *
- * Obtains the height of the `GtkPrintContext`, in pixels.
- *
- * Returns: the height of @context
- */
-double
-gtk_print_context_get_height (GtkPrintContext *context)
-{
-  GtkPrintOperationPrivate *priv;
-  double height;
-
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
-
-  priv = context->op->priv;
-
-  if (priv->use_full_page)
-    height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
-  else
-    height = gtk_page_setup_get_page_height (context->page_setup, GTK_UNIT_INCH);
-
-  /* Really dpi_y? What about landscape? what does dpi_y mean in that case? */
-  return height * context->surface_dpi_y / context->pixels_per_unit_y;
-}
-
-/**
- * gtk_print_context_get_dpi_x:
- * @context: a `GtkPrintContext`
- *
- * Obtains the horizontal resolution of the `GtkPrintContext`,
- * in dots per inch.
- *
- * Returns: the horizontal resolution of @context
- */
-double
-gtk_print_context_get_dpi_x (GtkPrintContext *context)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
-
-  return context->surface_dpi_x;
-}
-
-/**
- * gtk_print_context_get_dpi_y:
- * @context: a `GtkPrintContext`
- *
- * Obtains the vertical resolution of the `GtkPrintContext`,
- * in dots per inch.
- *
- * Returns: the vertical resolution of @context
- */
-double
-gtk_print_context_get_dpi_y (GtkPrintContext *context)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
-
-  return context->surface_dpi_y;
-}
-
-/**
- * gtk_print_context_get_hard_margins:
- * @context: a `GtkPrintContext`
- * @top: (out): top hardware printer margin
- * @bottom: (out): bottom hardware printer margin
- * @left: (out): left hardware printer margin
- * @right: (out): right hardware printer margin
- *
- * Obtains the hardware printer margins of the `GtkPrintContext`,
- * in units.
- *
- * Returns: %TRUE if the hard margins were retrieved
- */
-gboolean
-gtk_print_context_get_hard_margins (GtkPrintContext *context,
-                                   double          *top,
-                                   double          *bottom,
-                                   double          *left,
-                                   double          *right)
-{
-  if (context->has_hard_margins)
-    {
-      *top    = context->hard_margin_top / context->pixels_per_unit_y;
-      *bottom = context->hard_margin_bottom / context->pixels_per_unit_y;
-      *left   = context->hard_margin_left / context->pixels_per_unit_x;
-      *right  = context->hard_margin_right / context->pixels_per_unit_x;
-    }
-
-  return context->has_hard_margins;
-}
-
-/**
- * gtk_print_context_set_hard_margins:
- * @context: a `GtkPrintContext`
- * @top: top hardware printer margin
- * @bottom: bottom hardware printer margin
- * @left: left hardware printer margin
- * @right: right hardware printer margin
- *
- * Sets the hard margins in pixels.
- */
-void
-_gtk_print_context_set_hard_margins (GtkPrintContext *context,
-                                    double           top,
-                                    double           bottom,
-                                    double           left,
-                                    double           right)
-{
-  context->hard_margin_top    = top;
-  context->hard_margin_bottom = bottom;
-  context->hard_margin_left   = left;
-  context->hard_margin_right  = right;
-  context->has_hard_margins   = TRUE;
-}
-
-/**
- * gtk_print_context_get_pango_fontmap:
- * @context: a `GtkPrintContext`
- *
- * Returns a `PangoFontMap` that is suitable for use
- * with the `GtkPrintContext`.
- *
- * Returns: (transfer none): the font map of @context
- */
-PangoFontMap *
-gtk_print_context_get_pango_fontmap (GtkPrintContext *context)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
-
-  return _gtk_print_context_get_fontmap (context);
-}
-
-/**
- * gtk_print_context_create_pango_context:
- * @context: a `GtkPrintContext`
- *
- * Creates a new `PangoContext` that can be used with the
- * `GtkPrintContext`.
- *
- * Returns: (transfer full): a new Pango context for @context
- */
-PangoContext *
-gtk_print_context_create_pango_context (GtkPrintContext *context)
-{
-  PangoContext *pango_context;
-  cairo_font_options_t *options;
-
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
-  
-  pango_context = pango_font_map_create_context (_gtk_print_context_get_fontmap (context));
-
-  options = cairo_font_options_create ();
-  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
-  pango_cairo_context_set_font_options (pango_context, options);
-  cairo_font_options_destroy (options);
-  
-  /* We use the unit-scaled resolution, as we still want 
-   * fonts given in points to work 
-   */
-  pango_cairo_context_set_resolution (pango_context,
-                                     context->surface_dpi_y / context->pixels_per_unit_y);
-  return pango_context;
-}
-
-/**
- * gtk_print_context_create_pango_layout:
- * @context: a `GtkPrintContext`
- *
- * Creates a new `PangoLayout` that is suitable for use
- * with the `GtkPrintContext`.
- *
- * Returns: (transfer full): a new Pango layout for @context
- */
-PangoLayout *
-gtk_print_context_create_pango_layout (GtkPrintContext *context)
-{
-  PangoContext *pango_context;
-  PangoLayout *layout;
-
-  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
-
-  pango_context = gtk_print_context_create_pango_context (context);
-  layout = pango_layout_new (pango_context);
-
-  pango_cairo_update_context (context->cr, pango_context);
-  g_object_unref (pango_context);
-
-  return layout;
-}
diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c
deleted file mode 100644 (file)
index c4b0fab..0000000
+++ /dev/null
@@ -1,3282 +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/>.
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include <cairo-pdf.h>
-
-#include "gtkprintoperation-private.h"
-#include "gtkmarshalers.h"
-#include "gdk/gdkmarshalers.h"
-#include <glib/gi18n-lib.h>
-#include "gtkprivate.h"
-#include "deprecated/gtkmessagedialog.h"
-#include "gtkwindowgroup.h"
-#include "gtktypebuiltins.h"
-
-/**
- * GtkPrintOperation:
- *
- * `GtkPrintOperation` is the high-level, portable printing API.
- *
- * It looks a bit different than other GTK dialogs such as the
- * `GtkFileChooser`, since some platforms don’t expose enough
- * infrastructure to implement a good print dialog. On such
- * platforms, `GtkPrintOperation` uses the native print dialog.
- * On platforms which do not provide a native print dialog, GTK
- * uses its own, see [class@Gtk.PrintUnixDialog].
- *
- * The typical way to use the high-level printing API is to create
- * a `GtkPrintOperation` object with [ctor@Gtk.PrintOperation.new]
- * when the user selects to print. Then you set some properties on it,
- * e.g. the page size, any [class@Gtk.PrintSettings] from previous print
- * operations, the number of pages, the current page, etc.
- *
- * Then you start the print operation by calling [method@Gtk.PrintOperation.run].
- * It will then show a dialog, let the user select a printer and options.
- * When the user finished the dialog, various signals will be emitted on
- * the `GtkPrintOperation`, the main one being
- * [signal@Gtk.PrintOperation::draw-page], which you are supposed to handle
- * and render the page on the provided [class@Gtk.PrintContext] using Cairo.
- *
- * # The high-level printing API
- *
- * ```c
- * static GtkPrintSettings *settings = NULL;
- *
- * static void
- * do_print (void)
- * {
- *   GtkPrintOperation *print;
- *   GtkPrintOperationResult res;
- *
- *   print = gtk_print_operation_new ();
- *
- *   if (settings != NULL)
- *     gtk_print_operation_set_print_settings (print, settings);
- *
- *   g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), NULL);
- *   g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), NULL);
- *
- *   res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- *                                  GTK_WINDOW (main_window), NULL);
- *
- *   if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
- *     {
- *       if (settings != NULL)
- *         g_object_unref (settings);
- *       settings = g_object_ref (gtk_print_operation_get_print_settings (print));
- *     }
- *
- *   g_object_unref (print);
- * }
- * ```
- *
- * By default `GtkPrintOperation` uses an external application to do
- * print preview. To implement a custom print preview, an application
- * must connect to the preview signal. The functions
- * [method@Gtk.PrintOperationPreview.render_page],
- * [method@Gtk.PrintOperationPreview.end_preview] and
- * [method@Gtk.PrintOperationPreview.is_selected]
- * are useful when implementing a print preview.
- */
-
-#define SHOW_PROGRESS_TIME 1200
-
-
-enum
-{
-  DONE,
-  BEGIN_PRINT,
-  PAGINATE,
-  REQUEST_PAGE_SETUP,
-  DRAW_PAGE,
-  END_PRINT,
-  STATUS_CHANGED,
-  CREATE_CUSTOM_WIDGET,
-  CUSTOM_WIDGET_APPLY,
-  PREVIEW,
-  UPDATE_CUSTOM_WIDGET,
-  LAST_SIGNAL
-};
-
-enum 
-{
-  PROP_0,
-  PROP_DEFAULT_PAGE_SETUP,
-  PROP_PRINT_SETTINGS,
-  PROP_JOB_NAME,
-  PROP_N_PAGES,
-  PROP_CURRENT_PAGE,
-  PROP_USE_FULL_PAGE,
-  PROP_TRACK_PRINT_STATUS,
-  PROP_UNIT,
-  PROP_SHOW_PROGRESS,
-  PROP_ALLOW_ASYNC,
-  PROP_EXPORT_FILENAME,
-  PROP_STATUS,
-  PROP_STATUS_STRING,
-  PROP_CUSTOM_TAB_LABEL,
-  PROP_EMBED_PAGE_SETUP,
-  PROP_HAS_SELECTION,
-  PROP_SUPPORT_SELECTION,
-  PROP_N_PAGES_TO_PRINT
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-static int job_nr = 0;
-typedef struct _PrintPagesData PrintPagesData;
-
-static void          preview_iface_init      (GtkPrintOperationPreviewIface *iface);
-static GtkPageSetup *create_page_setup       (GtkPrintOperation             *op);
-static void          common_render_page      (GtkPrintOperation             *op,
-                                             int                            page_nr);
-static void          increment_page_sequence (PrintPagesData *data);
-static void          prepare_data            (PrintPagesData *data);
-static void          clamp_page_ranges       (PrintPagesData *data);
-
-
-G_DEFINE_TYPE_WITH_CODE (GtkPrintOperation, gtk_print_operation, G_TYPE_OBJECT,
-                         G_ADD_PRIVATE (GtkPrintOperation)
-                        G_IMPLEMENT_INTERFACE (GTK_TYPE_PRINT_OPERATION_PREVIEW,
-                                               preview_iface_init))
-
-/**
- * gtk_print_error_quark:
- *
- * Registers an error quark for `GtkPrintOperation` if necessary.
- * 
- * Returns: The error quark used for `GtkPrintOperation` errors.
- **/
-GQuark     
-gtk_print_error_quark (void)
-{
-  static GQuark quark = 0;
-  if (quark == 0)
-    quark = g_quark_from_static_string ("gtk-print-error-quark");
-  return quark;
-}
-     
-static void
-gtk_print_operation_finalize (GObject *object)
-{
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  if (priv->free_platform_data &&
-      priv->platform_data)
-    {
-      priv->free_platform_data (priv->platform_data);
-      priv->free_platform_data = NULL;
-    }
-
-  if (priv->default_page_setup)
-    g_object_unref (priv->default_page_setup);
-  
-  if (priv->print_settings)
-    g_object_unref (priv->print_settings);
-  
-  if (priv->print_context)
-    g_object_unref (priv->print_context);
-
-  g_free (priv->export_filename);
-  g_free (priv->job_name);
-  g_free (priv->custom_tab_label);
-  g_free (priv->status_string);
-
-  if (priv->print_pages_idle_id > 0)
-    g_source_remove (priv->print_pages_idle_id);
-
-  if (priv->show_progress_timeout_id > 0)
-    g_source_remove (priv->show_progress_timeout_id);
-
-  if (priv->error)
-    g_error_free (priv->error);
-  
-  G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object);
-}
-
-static void
-gtk_print_operation_init (GtkPrintOperation *operation)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (operation);
-  const char *appname;
-
-  priv->status = GTK_PRINT_STATUS_INITIAL;
-  priv->status_string = g_strdup ("");
-  priv->default_page_setup = NULL;
-  priv->print_settings = NULL;
-  priv->nr_of_pages = -1;
-  priv->nr_of_pages_to_print = -1;
-  priv->page_position = -1;
-  priv->current_page = -1;
-  priv->use_full_page = FALSE;
-  priv->show_progress = FALSE;
-  priv->export_filename = NULL;
-  priv->track_print_status = FALSE;
-  priv->is_sync = FALSE;
-  priv->support_selection = FALSE;
-  priv->has_selection = FALSE;
-  priv->embed_page_setup = FALSE;
-
-  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
-
-  priv->rloop = NULL;
-  priv->unit = GTK_UNIT_NONE;
-
-  appname = g_get_application_name ();
-  if (appname == NULL)
-    appname = "";
-  /* translators: this string is the default job title for print
-   * jobs. %s gets replaced by the application name, %d gets replaced
-   * by the job number.
-   */
-  priv->job_name = g_strdup_printf (_("%s job #%d"), appname, ++job_nr);
-  operation->priv = priv;
-}
-
-static void
-preview_iface_render_page (GtkPrintOperationPreview *preview,
-                          int                       page_nr)
-{
-
-  GtkPrintOperation *op;
-
-  op = GTK_PRINT_OPERATION (preview);
-  common_render_page (op, page_nr);
-}
-
-static void
-preview_iface_end_preview (GtkPrintOperationPreview *preview)
-{
-  GtkPrintOperation *op;
-  GtkPrintOperationResult result;
-  
-  op = GTK_PRINT_OPERATION (preview);
-
-  g_signal_emit (op, signals[END_PRINT], 0, op->priv->print_context);
-
-  if (op->priv->rloop)
-    g_main_loop_quit (op->priv->rloop);
-  
-  if (op->priv->end_run)
-    op->priv->end_run (op, op->priv->is_sync, TRUE);
-  
-  _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
-
-  if (op->priv->error)
-    result = GTK_PRINT_OPERATION_RESULT_ERROR;
-  else if (op->priv->cancelled)
-    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  else
-    result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
-  g_signal_emit (op, signals[DONE], 0, result);
-}
-
-static gboolean
-preview_iface_is_selected (GtkPrintOperationPreview *preview,
-                          int                       page_nr)
-{
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  int i;
-
-  switch (priv->print_pages)
-    {
-    case GTK_PRINT_PAGES_SELECTION:
-    case GTK_PRINT_PAGES_ALL:
-      return (page_nr >= 0) && (page_nr < priv->nr_of_pages);
-    case GTK_PRINT_PAGES_CURRENT:
-      return page_nr == priv->current_page;
-    case GTK_PRINT_PAGES_RANGES:
-      for (i = 0; i < priv->num_page_ranges; i++)
-       {
-         if (page_nr >= priv->page_ranges[i].start &&
-             (page_nr <= priv->page_ranges[i].end || priv->page_ranges[i].end == -1))
-           return TRUE;
-       }
-      return FALSE;
-    default:
-      return FALSE;
-    }
-}
-
-static void
-preview_iface_init (GtkPrintOperationPreviewIface *iface)
-{
-  iface->render_page = preview_iface_render_page;
-  iface->end_preview = preview_iface_end_preview;
-  iface->is_selected = preview_iface_is_selected;
-}
-
-static void
-preview_start_page (GtkPrintOperation *op,
-                   GtkPrintContext   *print_context,
-                   GtkPageSetup      *page_setup)
-{
-  if ((op->priv->manual_number_up < 2) ||
-      (op->priv->page_position % op->priv->manual_number_up == 0))
-    g_signal_emit_by_name (op, "got-page-size", print_context, page_setup);
-}
-
-static void
-preview_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
-preview_end_run (GtkPrintOperation *op,
-                gboolean           wait,
-                gboolean           cancelled)
-{
-  g_free (op->priv->page_ranges);
-  op->priv->page_ranges = NULL;
-}
-
-
-static void
-gtk_print_operation_set_property (GObject      *object,
-                                 guint         prop_id,
-                                 const GValue *value,
-                                 GParamSpec   *pspec)
-{
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
-  
-  switch (prop_id)
-    {
-    case PROP_DEFAULT_PAGE_SETUP:
-      gtk_print_operation_set_default_page_setup (op, g_value_get_object (value));
-      break;
-    case PROP_PRINT_SETTINGS:
-      gtk_print_operation_set_print_settings (op, g_value_get_object (value));
-      break;
-    case PROP_JOB_NAME:
-      gtk_print_operation_set_job_name (op, g_value_get_string (value));
-      break;
-    case PROP_N_PAGES:
-      gtk_print_operation_set_n_pages (op, g_value_get_int (value));
-      break;
-    case PROP_CURRENT_PAGE:
-      gtk_print_operation_set_current_page (op, g_value_get_int (value));
-      break;
-    case PROP_USE_FULL_PAGE:
-      gtk_print_operation_set_use_full_page (op, g_value_get_boolean (value));
-      break;
-    case PROP_TRACK_PRINT_STATUS:
-      gtk_print_operation_set_track_print_status (op, g_value_get_boolean (value));
-      break;
-    case PROP_UNIT:
-      gtk_print_operation_set_unit (op, g_value_get_enum (value));
-      break;
-    case PROP_ALLOW_ASYNC:
-      gtk_print_operation_set_allow_async (op, g_value_get_boolean (value));
-      break;
-    case PROP_SHOW_PROGRESS:
-      gtk_print_operation_set_show_progress (op, g_value_get_boolean (value));
-      break;
-    case PROP_EXPORT_FILENAME:
-      gtk_print_operation_set_export_filename (op, g_value_get_string (value));
-      break;
-    case PROP_CUSTOM_TAB_LABEL:
-      gtk_print_operation_set_custom_tab_label (op, g_value_get_string (value));
-      break;
-    case PROP_EMBED_PAGE_SETUP:
-      gtk_print_operation_set_embed_page_setup (op, g_value_get_boolean (value));
-      break;
-    case PROP_HAS_SELECTION:
-      gtk_print_operation_set_has_selection (op, g_value_get_boolean (value));
-      break;
-    case PROP_SUPPORT_SELECTION:
-      gtk_print_operation_set_support_selection (op, g_value_get_boolean (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gtk_print_operation_get_property (GObject    *object,
-                                 guint       prop_id,
-                                 GValue     *value,
-                                 GParamSpec *pspec)
-{
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  switch (prop_id)
-    {
-    case PROP_DEFAULT_PAGE_SETUP:
-      g_value_set_object (value, priv->default_page_setup);
-      break;
-    case PROP_PRINT_SETTINGS:
-      g_value_set_object (value, priv->print_settings);
-      break;
-    case PROP_JOB_NAME:
-      g_value_set_string (value, priv->job_name);
-      break;
-    case PROP_N_PAGES:
-      g_value_set_int (value, priv->nr_of_pages);
-      break;
-    case PROP_CURRENT_PAGE:
-      g_value_set_int (value, priv->current_page);
-      break;      
-    case PROP_USE_FULL_PAGE:
-      g_value_set_boolean (value, priv->use_full_page);
-      break;
-    case PROP_TRACK_PRINT_STATUS:
-      g_value_set_boolean (value, priv->track_print_status);
-      break;
-    case PROP_UNIT:
-      g_value_set_enum (value, priv->unit);
-      break;
-    case PROP_ALLOW_ASYNC:
-      g_value_set_boolean (value, priv->allow_async);
-      break;
-    case PROP_SHOW_PROGRESS:
-      g_value_set_boolean (value, priv->show_progress);
-      break;
-    case PROP_EXPORT_FILENAME:
-      g_value_set_string (value, priv->export_filename);
-      break;
-    case PROP_STATUS:
-      g_value_set_enum (value, priv->status);
-      break;
-    case PROP_STATUS_STRING:
-      g_value_set_string (value, priv->status_string);
-      break;
-    case PROP_CUSTOM_TAB_LABEL:
-      g_value_set_string (value, priv->custom_tab_label);
-      break;
-    case PROP_EMBED_PAGE_SETUP:
-      g_value_set_boolean (value, priv->embed_page_setup);
-      break;
-    case PROP_HAS_SELECTION:
-      g_value_set_boolean (value, priv->has_selection);
-      break;
-    case PROP_SUPPORT_SELECTION:
-      g_value_set_boolean (value, priv->support_selection);
-      break;
-    case PROP_N_PAGES_TO_PRINT:
-      g_value_set_int (value, priv->nr_of_pages_to_print);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-struct _PrintPagesData
-{
-  GtkPrintOperation *op;
-  int uncollated_copies;
-  int collated_copies;
-  int uncollated, collated, total;
-
-  int range, num_ranges;
-  GtkPageRange *ranges;
-  GtkPageRange one_range;
-
-  int page;
-  int sheet;
-  int first_position, last_position;
-  int first_sheet;
-  int num_of_sheets;
-  int *pages;
-
-  GtkWidget *progress;
-  gboolean initialized;
-  gboolean is_preview;
-  gboolean done;
-};
-
-typedef struct
-{
-  GtkPrintOperationPreview *preview;
-  GtkPrintContext *print_context;
-  GtkWindow *parent;
-  cairo_surface_t *surface;
-  char *filename;
-  gboolean wait;
-  PrintPagesData *pages_data;
-} PreviewOp;
-
-static void
-preview_print_idle_done (gpointer data)
-{
-  GtkPrintOperation *op;
-  PreviewOp *pop = (PreviewOp *) data;
-
-  op = GTK_PRINT_OPERATION (pop->preview);
-
-  cairo_surface_finish (pop->surface);
-
-  if (op->priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED)
-    {
-      cairo_surface_destroy (pop->surface);
-    }
-  else
-    {
-      /* Surface is destroyed in launch_preview */
-      _gtk_print_operation_platform_backend_launch_preview (op,
-                                                           pop->surface,
-                                                           pop->parent,
-                                                           pop->filename);
-    }
-
-  g_free (pop->filename);
-
-  gtk_print_operation_preview_end_preview (pop->preview);
-
-  g_object_unref (pop->pages_data->op);
-  g_free (pop->pages_data->pages);
-  g_free (pop->pages_data);
-
-  g_object_unref (op);
-  g_free (pop);
-}
-
-static gboolean
-preview_print_idle (gpointer data)
-{
-  PreviewOp *pop = (PreviewOp *) data;
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (pop->preview);
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  gboolean done = FALSE;
-
-  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
-    {
-      if (priv->cancelled)
-       {
-         done = TRUE;
-          _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-       }
-      else if (!pop->pages_data->initialized)
-        {
-          pop->pages_data->initialized = TRUE;
-          prepare_data (pop->pages_data);
-        }
-      else
-        {
-          increment_page_sequence (pop->pages_data);
-
-          if (!pop->pages_data->done)
-            gtk_print_operation_preview_render_page (pop->preview, pop->pages_data->page);
-          else
-            done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
-        }
-    }
-
-  return !done;
-}
-
-static void
-preview_got_page_size (GtkPrintOperationPreview *preview, 
-                      GtkPrintContext          *context,
-                      GtkPageSetup             *page_setup,
-                      PreviewOp                *pop)
-{
-  GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
-  cairo_t *cr;
-
-  _gtk_print_operation_platform_backend_resize_preview_surface (op, page_setup, pop->surface);
-
-  cr = gtk_print_context_get_cairo_context (pop->print_context);
-  _gtk_print_operation_platform_backend_preview_start_page (op, pop->surface, cr);
-
-}
-
-static void
-preview_ready (GtkPrintOperationPreview *preview,
-               GtkPrintContext          *context,
-              PreviewOp                *pop)
-{
-  guint id;
-
-  pop->print_context = context;
-
-  g_object_ref (preview);
-      
-  id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
-                        preview_print_idle,
-                        pop,
-                        preview_print_idle_done);
-  gdk_source_set_static_name_by_id (id, "[gtk] preview_print_idle");
-}
-
-
-static gboolean
-gtk_print_operation_preview_handler (GtkPrintOperation        *op,
-                                     GtkPrintOperationPreview *preview, 
-                                    GtkPrintContext          *context,
-                                    GtkWindow                *parent)
-{
-  double dpi_x, dpi_y;
-  PreviewOp *pop;
-  GtkPageSetup *page_setup;
-  cairo_t *cr;
-
-  pop = g_new0 (PreviewOp, 1);
-  pop->filename = NULL;
-  pop->preview = preview;
-  pop->parent = parent;
-  pop->pages_data = g_new0 (PrintPagesData, 1);
-  pop->pages_data->op = g_object_ref (GTK_PRINT_OPERATION (preview));
-  pop->pages_data->is_preview = TRUE;
-
-  page_setup = gtk_print_context_get_page_setup (context);
-
-  pop->surface =
-    _gtk_print_operation_platform_backend_create_preview_surface (op,
-                                                                 page_setup,
-                                                                 &dpi_x, &dpi_y,
-                                                                 &pop->filename);
-
-  if (pop->surface == NULL)
-    {
-      g_free (pop);
-      return FALSE;
-    }
-
-  cr = cairo_create (pop->surface);
-  gtk_print_context_set_cairo_context (op->priv->print_context, cr,
-                                      dpi_x, dpi_y);
-  cairo_destroy (cr);
-
-  g_signal_connect (preview, "ready", (GCallback) preview_ready, pop);
-  g_signal_connect (preview, "got-page-size", (GCallback) preview_got_page_size, pop);
-  
-  return TRUE;
-}
-
-static GtkWidget *
-gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
-{
-  return NULL;
-}
-
-static gboolean
-gtk_print_operation_paginate (GtkPrintOperation *operation,
-                              GtkPrintContext   *context)
-{
-  /* assume the number of pages is already set and pagination is not needed */
-  return TRUE;
-}
-
-static void
-gtk_print_operation_done (GtkPrintOperation       *operation,
-                          GtkPrintOperationResult  result)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (operation);
-
-  if (priv->print_context)
-    {
-      g_object_unref (priv->print_context);
-      priv->print_context = NULL;
-    } 
-}
-
-static gboolean
-custom_widget_accumulator (GSignalInvocationHint *ihint,
-                          GValue                *return_accu,
-                          const GValue          *handler_return,
-                          gpointer               dummy)
-{
-  gboolean continue_emission;
-  GtkWidget *widget;
-  
-  widget = g_value_get_object (handler_return);
-  if (widget != NULL)
-    g_value_set_object (return_accu, widget);
-  continue_emission = (widget == NULL);
-  
-  return continue_emission;
-}
-
-static gboolean
-paginate_accumulator (GSignalInvocationHint *ihint,
-                      GValue                *return_accu,
-                      const GValue          *handler_return,
-                      gpointer               dummy)
-{
-  *return_accu = *handler_return;
-
-  /* Stop signal emission on first invocation, so if it's a callback then
-   * the default handler won't run. */
-  return FALSE;
-}
-
-static void
-gtk_print_operation_class_init (GtkPrintOperationClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->set_property = gtk_print_operation_set_property;
-  gobject_class->get_property = gtk_print_operation_get_property;
-  gobject_class->finalize = gtk_print_operation_finalize;
-  class->preview = gtk_print_operation_preview_handler; 
-  class->create_custom_widget = gtk_print_operation_create_custom_widget;
-  class->paginate = gtk_print_operation_paginate;
-  class->done = gtk_print_operation_done;
-
-  /**
-   * GtkPrintOperation::done:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @result: the result of the print operation
-   *
-   * Emitted when the print operation run has finished doing
-   * everything required for printing.
-   *
-   * @result gives you information about what happened during the run.
-   * If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
-   * [method@Gtk.PrintOperation.get_error] for more information.
-   *
-   * If you enabled print status tracking then
-   * [method@Gtk.PrintOperation.is_finished] may still return %FALSE
-   * after the ::done signal was emitted.
-   */
-  signals[DONE] =
-    g_signal_new (I_("done"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, done),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_OPERATION_RESULT);
-
-  /**
-   * GtkPrintOperation::begin-print:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @context: the `GtkPrintContext` for the current operation
-   *
-   * Emitted after the user has finished changing print settings
-   * in the dialog, before the actual rendering starts.
-   *
-   * A typical use for ::begin-print is to use the parameters from the
-   * [class@Gtk.PrintContext] and paginate the document accordingly,
-   * and then set the number of pages with
-   * [method@Gtk.PrintOperation.set_n_pages].
-   */
-  signals[BEGIN_PRINT] =
-    g_signal_new (I_("begin-print"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, begin_print),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
-
-   /**
-   * GtkPrintOperation::paginate:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @context: the `GtkPrintContext` for the current operation
-   *
-   * Emitted after the ::begin-print signal, but before the actual rendering
-   * starts.
-   *
-   * It keeps getting emitted until a connected signal handler returns %TRUE.
-   *
-   * The ::paginate signal is intended to be used for paginating a document
-   * in small chunks, to avoid blocking the user interface for a long
-   * time. The signal handler should update the number of pages using
-   * [method@Gtk.PrintOperation.set_n_pages], and return %TRUE if the document
-   * has been completely paginated.
-   *
-   * If you don't need to do pagination in chunks, you can simply do
-   * it all in the ::begin-print handler, and set the number of pages
-   * from there.
-   *
-   * Returns: %TRUE if pagination is complete
-   */
-  signals[PAGINATE] =
-    g_signal_new (I_("paginate"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkPrintOperationClass, paginate),
-                  paginate_accumulator, NULL,
-                  _gdk_marshal_BOOLEAN__OBJECT,
-                  G_TYPE_BOOLEAN, 1, GTK_TYPE_PRINT_CONTEXT);
-  g_signal_set_va_marshaller (signals[PAGINATE],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gdk_marshal_BOOLEAN__OBJECTv);
-
-  /**
-   * GtkPrintOperation::request-page-setup:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @context: the `GtkPrintContext` for the current operation
-   * @page_nr: the number of the currently printed page (0-based)
-   * @setup: the `GtkPageSetup`
-   *
-   * Emitted once for every page that is printed.
-   *
-   * This gives the application a chance to modify the page setup.
-   * Any changes done to @setup will be in force only for printing
-   * this page.
-   */
-  signals[REQUEST_PAGE_SETUP] =
-    g_signal_new (I_("request-page-setup"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GtkPrintOperationClass, request_page_setup),
-                  NULL, NULL,
-                  _gtk_marshal_VOID__OBJECT_INT_OBJECT,
-                  G_TYPE_NONE, 3,
-                  GTK_TYPE_PRINT_CONTEXT,
-                  G_TYPE_INT,
-                  GTK_TYPE_PAGE_SETUP);
-  g_signal_set_va_marshaller (signals[REQUEST_PAGE_SETUP],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gtk_marshal_VOID__OBJECT_INT_OBJECTv);
-
-  /**
-   * GtkPrintOperation::draw-page:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @context: the `GtkPrintContext` for the current operation
-   * @page_nr: the number of the currently printed page (0-based)
-   *
-   * Emitted for every page that is printed.
-   *
-   * The signal handler must render the @page_nr's page onto the cairo
-   * context obtained from @context using
-   * [method@Gtk.PrintContext.get_cairo_context].
-   *
-   * ```c
-   * static void
-   * draw_page (GtkPrintOperation *operation,
-   *            GtkPrintContext   *context,
-   *            int                page_nr,
-   *            gpointer           user_data)
-   * {
-   *   cairo_t *cr;
-   *   PangoLayout *layout;
-   *   double width, text_height;
-   *   int layout_height;
-   *   PangoFontDescription *desc;
-   *   
-   *   cr = gtk_print_context_get_cairo_context (context);
-   *   width = gtk_print_context_get_width (context);
-   *   
-   *   cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
-   *   
-   *   cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
-   *   cairo_fill (cr);
-   *   
-   *   layout = gtk_print_context_create_pango_layout (context);
-   *   
-   *   desc = pango_font_description_from_string ("sans 14");
-   *   pango_layout_set_font_description (layout, desc);
-   *   pango_font_description_free (desc);
-   *   
-   *   pango_layout_set_text (layout, "some text", -1);
-   *   pango_layout_set_width (layout, width * PANGO_SCALE);
-   *   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
-   *                         
-   *   pango_layout_get_size (layout, NULL, &layout_height);
-   *   text_height = (double)layout_height / PANGO_SCALE;
-   *   
-   *   cairo_move_to (cr, width / 2,  (HEADER_HEIGHT - text_height) / 2);
-   *   pango_cairo_show_layout (cr, layout);
-   *   
-   *   g_object_unref (layout);
-   * }
-   * ```
-   *
-   * Use [method@Gtk.PrintOperation.set_use_full_page] and
-   * [method@Gtk.PrintOperation.set_unit] before starting the print
-   * operation to set up the transformation of the cairo context
-   * according to your needs.
-   */
-  signals[DRAW_PAGE] =
-    g_signal_new (I_("draw-page"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, draw_page),
-                 NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_INT,
-                 G_TYPE_NONE, 2,
-                 GTK_TYPE_PRINT_CONTEXT,
-                 G_TYPE_INT);
-  g_signal_set_va_marshaller (signals[DRAW_PAGE],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gtk_marshal_VOID__OBJECT_INTv);
-
-  /**
-   * GtkPrintOperation::end-print:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @context: the `GtkPrintContext` for the current operation
-   *
-   * Emitted after all pages have been rendered.
-   *
-   * A handler for this signal can clean up any resources that have
-   * been allocated in the [signal@Gtk.PrintOperation::begin-print] handler.
-   */
-  signals[END_PRINT] =
-    g_signal_new (I_("end-print"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, end_print),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
-
-  /**
-   * GtkPrintOperation::status-changed:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   *
-   * Emitted at between the various phases of the print operation.
-   *
-   * See [enum@Gtk.PrintStatus] for the phases that are being discriminated.
-   * Use [method@Gtk.PrintOperation.get_status] to find out the current
-   * status.
-   */
-  signals[STATUS_CHANGED] =
-    g_signal_new (I_("status-changed"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 0);
-
-
-  /**
-   * GtkPrintOperation::create-custom-widget:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   *
-   * Emitted when displaying the print dialog.
-   *
-   * If you return a widget in a handler for this signal it will be
-   * added to a custom tab in the print dialog. You typically return a
-   * container widget with multiple widgets in it.
-   *
-   * The print dialog owns the returned widget, and its lifetime is not
-   * controlled by the application. However, the widget is guaranteed
-   * to stay around until the [signal@Gtk.PrintOperation::custom-widget-apply]
-   * signal is emitted on the operation. Then you can read out any
-   * information you need from the widgets.
-   *
-   * Returns: (nullable) (transfer none): A custom widget that gets embedded in
-   *   the print dialog
-   */
-  signals[CREATE_CUSTOM_WIDGET] =
-    g_signal_new (I_("create-custom-widget"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
-                 custom_widget_accumulator, NULL,
-                 _gtk_marshal_OBJECT__VOID,
-                 G_TYPE_OBJECT, 0);
-  g_signal_set_va_marshaller (signals[CREATE_CUSTOM_WIDGET],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gtk_marshal_OBJECT__VOIDv);
-
-  /**
-   * GtkPrintOperation::update-custom-widget:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @widget: the custom widget added in ::create-custom-widget
-   * @setup: actual page setup
-   * @settings: actual print settings
-   *
-   * Emitted after change of selected printer.
-   *
-   * The actual page setup and print settings are passed to the custom
-   * widget, which can actualize itself according to this change.
-   */
-  signals[UPDATE_CUSTOM_WIDGET] =
-    g_signal_new (I_("update-custom-widget"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, update_custom_widget),
-                 NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_OBJECT_OBJECT,
-                 G_TYPE_NONE, 3, GTK_TYPE_WIDGET, GTK_TYPE_PAGE_SETUP, GTK_TYPE_PRINT_SETTINGS);
-  g_signal_set_va_marshaller (signals[UPDATE_CUSTOM_WIDGET],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gtk_marshal_VOID__OBJECT_OBJECT_OBJECTv);
-
-  /**
-   * GtkPrintOperation::custom-widget-apply:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @widget: the custom widget added in ::create-custom-widget
-   *
-   * Emitted right before ::begin-print if you added
-   * a custom widget in the ::create-custom-widget handler.
-   *
-   * When you get this signal you should read the information from the
-   * custom widgets, as the widgets are not guaranteed to be around at a
-   * later time.
-   */
-  signals[CUSTOM_WIDGET_APPLY] =
-    g_signal_new (I_("custom-widget-apply"),
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
-   /**
-   * GtkPrintOperation::preview:
-   * @operation: the `GtkPrintOperation` on which the signal was emitted
-   * @preview: the `GtkPrintOperationPreview` for the current operation
-   * @context: the `GtkPrintContext` that will be used
-   * @parent: (nullable): the `GtkWindow` to use as window parent
-   *
-   * Gets emitted when a preview is requested from the native dialog.
-   *
-   * The default handler for this signal uses an external viewer
-   * application to preview.
-   *
-   * To implement a custom print preview, an application must return
-   * %TRUE from its handler for this signal. In order to use the
-   * provided @context for the preview implementation, it must be
-   * given a suitable cairo context with
-   * [method@Gtk.PrintContext.set_cairo_context].
-   *
-   * The custom preview implementation can use
-   * [method@Gtk.PrintOperationPreview.is_selected] and
-   * [method@Gtk.PrintOperationPreview.render_page] to find pages which
-   * are selected for print and render them. The preview must be
-   * finished by calling [method@Gtk.PrintOperationPreview.end_preview]
-   * (typically in response to the user clicking a close button).
-   *
-   * Returns: %TRUE if the listener wants to take over control of the preview
-   */
-  signals[PREVIEW] =
-    g_signal_new (I_("preview"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_LAST,
-                 G_STRUCT_OFFSET (GtkPrintOperationClass, preview),
-                 _gtk_boolean_handled_accumulator, NULL,
-                 _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
-                 G_TYPE_BOOLEAN, 3,
-                 GTK_TYPE_PRINT_OPERATION_PREVIEW,
-                 GTK_TYPE_PRINT_CONTEXT,
-                 GTK_TYPE_WINDOW);
-  g_signal_set_va_marshaller (signals[PREVIEW],
-                              G_TYPE_FROM_CLASS (gobject_class),
-                              _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECTv);
-
-  /**
-   * GtkPrintOperation:default-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_default_page_setup org.gtk.Property.set=gtk_print_operation_set_default_page_setup)
-   *
-   * The `GtkPageSetup` used by default.
-   *
-   * This page setup will be used by [method@Gtk.PrintOperation.run],
-   * but it can be overridden on a per-page basis by connecting
-   * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_DEFAULT_PAGE_SETUP,
-                                  g_param_spec_object ("default-page-setup", NULL, NULL,
-                                                       GTK_TYPE_PAGE_SETUP,
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintOperation:print-settings: (attributes org.gtk.Property.get=gtk_print_operation_get_print_settings org.gtk.Property.set=gtk_print_operation_set_print_settings)
-   *
-   * The `GtkPrintSettings` used for initializing the dialog.
-   *
-   * Setting this property is typically used to re-establish
-   * print settings from a previous print operation, see
-   * [method@Gtk.PrintOperation.run].
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_PRINT_SETTINGS,
-                                  g_param_spec_object ("print-settings", NULL, NULL,
-                                                       GTK_TYPE_PRINT_SETTINGS,
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintOperation:job-name: (attributes org.gtk.Property.set=gtk_print_operation_set_job_name)
-   *
-   * A string used to identify the job (e.g. in monitoring
-   * applications like eggcups).
-   *
-   * If you don't set a job name, GTK picks a default one
-   * by numbering successive print jobs.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_JOB_NAME,
-                                  g_param_spec_string ("job-name", NULL, NULL,
-                                                       "",
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintOperation:n-pages: (attributes org.gtk.Property.set=gtk_print_operation_set_n_pages)
-   *
-   * The number of pages in the document.
-   *
-   * This must be set to a positive number before the rendering
-   * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
-   * signal handler.
-   *
-   * Note that the page numbers passed to the
-   * [signal@Gtk.PrintOperation::request-page-setup] and
-   * [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
-   * if the user chooses to print all pages, the last ::draw-page signal
-   * will be for page @n_pages - 1.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_N_PAGES,
-                                  g_param_spec_int ("n-pages", NULL, NULL,
-                                                    -1,
-                                                    G_MAXINT,
-                                                    -1,
-                                                    GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:current-page: (attributes org.gtk.Property.set=gtk_print_operation_set_current_page)
-   *
-   * The current page in the document.
-   *
-   * If this is set before [method@Gtk.PrintOperation.run],
-   * the user will be able to select to print only the current page.
-   *
-   * Note that this only makes sense for pre-paginated documents.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_CURRENT_PAGE,
-                                  g_param_spec_int ("current-page", NULL, NULL,
-                                                    -1,
-                                                    G_MAXINT,
-                                                    -1,
-                                                    GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:use-full-page: (attributes org.gtk.Property.set=gtk_print_operation_set_use_full_page)
-   *
-   * If %TRUE, the transformation for the cairo context obtained
-   * from `GtkPrintContext` puts the origin at the top left corner
-   * of the page.
-   *
-   * This may not be the top left corner of the sheet, depending on
-   * page orientation and the number of pages per sheet. Otherwise,
-   * the origin is at the top left corner of the imageable area (i.e.
-   * inside the margins).
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_USE_FULL_PAGE,
-                                  g_param_spec_boolean ("use-full-page", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:track-print-status: (attributes org.gtk.Property.set=gtk_print_operation_set_track_print_status)
-   *
-   * If %TRUE, the print operation 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.
-   * However, this is often implemented using polling, and should
-   * not be enabled unless needed.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_TRACK_PRINT_STATUS,
-                                  g_param_spec_boolean ("track-print-status", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:unit: (attributes org.gtk.Property.set=gtk_print_operation_set_unit)
-   *
-   * The transformation for the cairo context obtained from
-   * `GtkPrintContext` is set up in such a way that distances
-   * are measured in units of @unit.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_UNIT,
-                                  g_param_spec_enum ("unit", NULL, NULL,
-                                                     GTK_TYPE_UNIT,
-                                                     GTK_UNIT_NONE,
-                                                     GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:show-progress: (attributes org.gtk.Property.set=gtk_print_operation_set_show_progress)
-   *
-   * Determines whether to show a progress dialog during the
-   * print operation.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_SHOW_PROGRESS,
-                                  g_param_spec_boolean ("show-progress", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:allow-async: (attributes org.gtk.Property.set=gtk_print_operation_set_allow_async)
-   *
-   * Determines whether the print operation may run asynchronously or not.
-   *
-   * Some systems don't support asynchronous printing, but those that do
-   * will return %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS as the status, and
-   * emit the [signal@Gtk.PrintOperation::done] signal when the operation
-   * is actually done.
-   *
-   * The Windows port does not support asynchronous operation at all (this
-   * is unlikely to change). On other platforms, all actions except for
-   * %GTK_PRINT_OPERATION_ACTION_EXPORT support asynchronous operation.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_ALLOW_ASYNC,
-                                  g_param_spec_boolean ("allow-async", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:export-filename: (attributes org.gtk.Property.set=gtk_print_operation_set_export_filename)
-   *
-   * The name of a file to generate instead of showing the print dialog.
-   *
-   * Currently, PDF is the only supported format.
-   *
-   * The intended use of this property is for implementing
-   * “Export to PDF” actions.
-   *
-   * “Print to PDF” support is independent of this and is done
-   * by letting the user pick the “Print to PDF” item from the
-   * list of printers in the print dialog.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_EXPORT_FILENAME,
-                                  g_param_spec_string ("export-filename", NULL, NULL,
-                                                       NULL,
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintOperation:status: (attributes org.gtk.Property.get=gtk_print_operation_get_status)
-   *
-   * The status of the print operation.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_STATUS,
-                                  g_param_spec_enum ("status", NULL, NULL,
-                                                     GTK_TYPE_PRINT_STATUS,
-                                                     GTK_PRINT_STATUS_INITIAL,
-                                                     GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:status-string: (attributes org.gtk.Property.get=gtk_print_operation_get_status_string)
-   *
-   * A string representation of the status of the print operation.
-   *
-   * The string is translated and suitable for displaying the print
-   * status e.g. in a `GtkStatusbar`.
-   *
-   * See the [property@Gtk.PrintOperation:status] property for a status
-   * value that is suitable for programmatic use.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_STATUS_STRING,
-                                  g_param_spec_string ("status-string", NULL, NULL,
-                                                       "",
-                                                       GTK_PARAM_READABLE));
-  
-
-  /**
-   * GtkPrintOperation:custom-tab-label: (attributes org.gtk.Property.set=gtk_print_operation_set_custom_tab_label)
-   *
-   * Used as the label of the tab containing custom widgets.
-   *
-   * Note that this property may be ignored on some platforms.
-   *
-   * If this is %NULL, GTK uses a default label.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_CUSTOM_TAB_LABEL,
-                                  g_param_spec_string ("custom-tab-label", NULL, NULL,
-                                                       NULL,
-                                                       GTK_PARAM_READWRITE));
-
-  /**
-   * GtkPrintOperation:support-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_support_selection org.gtk.Property.set=gtk_print_operation_set_support_selection)
-   *
-   * If %TRUE, the print operation will support print of selection.
-   *
-   * This allows the print dialog to show a "Selection" button.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_SUPPORT_SELECTION,
-                                  g_param_spec_boolean ("support-selection", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:has-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_has_selection org.gtk.Property.set=gtk_print_operation_set_has_selection)
-   *
-   * Determines whether there is a selection in your application.
-   *
-   * This can allow your application to print the selection.
-   * This is typically used to make a "Selection" button sensitive.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_HAS_SELECTION,
-                                  g_param_spec_boolean ("has-selection", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-
-  /**
-   * GtkPrintOperation:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_embed_page_setup org.gtk.Property.set=gtk_print_operation_set_embed_page_setup)
-   *
-   * If %TRUE, page size combo box and orientation combo box
-   * are embedded into page setup page.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_EMBED_PAGE_SETUP,
-                                  g_param_spec_boolean ("embed-page-setup", NULL, NULL,
-                                                        FALSE,
-                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
-
-  /**
-   * GtkPrintOperation:n-pages-to-print: (attributes org.gtk.Property.get=gtk_print_operation_get_n_pages_to_print)
-   *
-   * The number of pages that will be printed.
-   *
-   * Note that this value is set during print preparation phase
-   * (%GTK_PRINT_STATUS_PREPARING), so this value should never be
-   * get before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
-   * You can connect to the [signal@Gtk.PrintOperation::status-changed] signal
-   * and call [method@Gtk.PrintOperation.get_n_pages_to_print] when
-   * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
-   *
-   * This is typically used to track the progress of print operation.
-   */
-  g_object_class_install_property (gobject_class,
-                                  PROP_N_PAGES_TO_PRINT,
-                                  g_param_spec_int ("n-pages-to-print", NULL, NULL,
-                                                    -1,
-                                                    G_MAXINT,
-                                                    -1,
-                                                    GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
-}
-
-/**
- * gtk_print_operation_new:
- *
- * Creates a new `GtkPrintOperation`.
- *
- * Returns: a new `GtkPrintOperation`
- */
-GtkPrintOperation *
-gtk_print_operation_new (void)
-{
-  GtkPrintOperation *print_operation;
-
-  print_operation = g_object_new (GTK_TYPE_PRINT_OPERATION, NULL);
-  
-  return print_operation;
-}
-
-/**
- * gtk_print_operation_set_default_page_setup: (attributes org.gtk.Method.set_property=default-page-setup)
- * @op: a `GtkPrintOperation`
- * @default_page_setup: (nullable): a `GtkPageSetup`
- *
- * Makes @default_page_setup the default page setup for @op.
- *
- * This page setup will be used by [method@Gtk.PrintOperation.run],
- * but it can be overridden on a per-page basis by connecting
- * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
- **/
-void
-gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
-                                           GtkPageSetup      *default_page_setup)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  g_return_if_fail (default_page_setup == NULL ||
-                    GTK_IS_PAGE_SETUP (default_page_setup));
-
-  if (default_page_setup != priv->default_page_setup)
-    {
-      if (default_page_setup)
-       g_object_ref (default_page_setup);
-      
-      if (priv->default_page_setup)
-       g_object_unref (priv->default_page_setup);
-      
-      priv->default_page_setup = default_page_setup;
-     
-      g_object_notify (G_OBJECT (op), "default-page-setup");
-    }
-}
-
-/**
- * gtk_print_operation_get_default_page_setup: (attributes org.gtk.Method.get_property=default-page-setup)
- * @op: a `GtkPrintOperation`
- *
- * Returns the default page setup.
- *
- * Returns: (transfer none): the default page setup
- */
-GtkPageSetup *
-gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
-
-  return op->priv->default_page_setup;
-}
-
-
-/**
- * gtk_print_operation_set_print_settings: (attributes org.gtk.Method.set_property=print-settings)
- * @op: a `GtkPrintOperation`
- * @print_settings: (nullable): `GtkPrintSettings`
- *
- * Sets the print settings for @op.
- *
- * This is typically used to re-establish print settings
- * from a previous print operation, see [method@Gtk.PrintOperation.run].
- */
-void
-gtk_print_operation_set_print_settings (GtkPrintOperation *op,
-                                       GtkPrintSettings  *print_settings)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  g_return_if_fail (print_settings == NULL || 
-                    GTK_IS_PRINT_SETTINGS (print_settings));
-
-  if (print_settings != priv->print_settings)
-    {
-      if (print_settings)
-        g_object_ref (print_settings);
-
-      if (priv->print_settings)
-        g_object_unref (priv->print_settings);
-  
-      priv->print_settings = print_settings;
-
-      g_object_notify (G_OBJECT (op), "print-settings");
-    }
-}
-
-/**
- * gtk_print_operation_get_print_settings: (attributes org.gtk.Method.get_property=print-settings)
- * @op: a `GtkPrintOperation`
- *
- * Returns the current print settings.
- *
- * Note that the return value is %NULL until either
- * [method@Gtk.PrintOperation.set_print_settings] or
- * [method@Gtk.PrintOperation.run] have been called.
- *
- * Returns: (transfer none) (nullable): the current print settings of @op.
- **/
-GtkPrintSettings *
-gtk_print_operation_get_print_settings (GtkPrintOperation *op)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
-
-  return op->priv->print_settings;
-}
-
-/**
- * gtk_print_operation_set_job_name: (attributes org.gtk.Method.set_property=job-name)
- * @op: a `GtkPrintOperation`
- * @job_name: a string that identifies the print job
- *
- * Sets the name of the print job.
- *
- * The name is used to identify the job (e.g. in monitoring
- * applications like eggcups).
- *
- * If you don’t set a job name, GTK picks a default one by
- * numbering successive print jobs.
- */
-void
-gtk_print_operation_set_job_name (GtkPrintOperation *op,
-                                 const char        *job_name)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  g_return_if_fail (job_name != NULL);
-
-  if (g_strcmp0 (priv->job_name, job_name) == 0)
-    return;
-
-  g_free (priv->job_name);
-  priv->job_name = g_strdup (job_name);
-
-  g_object_notify (G_OBJECT (op), "job-name");
-}
-
-/**
- * gtk_print_operation_set_n_pages: (attributes org.gtk.Method.set_property=n-pages)
- * @op: a `GtkPrintOperation`
- * @n_pages: the number of pages
- *
- * Sets the number of pages in the document.
- *
- * This must be set to a positive number before the rendering
- * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
- * signal handler.
- *
- * Note that the page numbers passed to the
- * [signal@Gtk.PrintOperation::request-page-setup]
- * and [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
- * if the user chooses to print all pages, the last ::draw-page signal
- * will be for page @n_pages - 1.
- */
-void
-gtk_print_operation_set_n_pages (GtkPrintOperation *op,
-                                int                n_pages)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  g_return_if_fail (n_pages > 0);
-  g_return_if_fail (priv->current_page == -1 || 
-                    priv->current_page < n_pages);
-
-  if (priv->nr_of_pages != n_pages)
-    {
-      priv->nr_of_pages = n_pages;
-
-      g_object_notify (G_OBJECT (op), "n-pages");
-    }
-}
-
-/**
- * gtk_print_operation_set_current_page: (attributes org.gtk.Method.set_property=current-page)
- * @op: a `GtkPrintOperation`
- * @current_page: the current page, 0-based
- *
- * Sets the current page.
- *
- * If this is called before [method@Gtk.PrintOperation.run],
- * the user will be able to select to print only the current page.
- *
- * Note that this only makes sense for pre-paginated documents.
- */
-void
-gtk_print_operation_set_current_page (GtkPrintOperation *op,
-                                     int                current_page)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  g_return_if_fail (current_page >= 0);
-  g_return_if_fail (priv->nr_of_pages == -1 || 
-                   current_page < priv->nr_of_pages);
-
-  if (priv->current_page != current_page)
-    {
-      priv->current_page = current_page;
-
-      g_object_notify (G_OBJECT (op), "current-page");
-    }
-}
-
-/**
- * gtk_print_operation_set_use_full_page: (attributes org.gtk.Method.set_property=use-full-page)
- * @op: a `GtkPrintOperation`
- * @full_page: %TRUE to set up the `GtkPrintContext` for the full page
- *
- * If @full_page is %TRUE, the transformation for the cairo context
- * obtained from `GtkPrintContext` puts the origin at the top left
- * corner of the page.
- *
- * This may not be the top left corner of the sheet, depending on page
- * orientation and the number of pages per sheet). Otherwise, the origin
- * is at the top left corner of the imageable area (i.e. inside the margins).
- */
-void
-gtk_print_operation_set_use_full_page (GtkPrintOperation *op,
-                                      gboolean           full_page)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  full_page = full_page != FALSE;
-
-  if (priv->use_full_page != full_page)
-    {
-      priv->use_full_page = full_page;
-   
-      g_object_notify (G_OBJECT (op), "use-full-page");
-    }
-}
-
-/**
- * gtk_print_operation_set_unit: (attributes org.gtk.Method.set_property=unit)
- * @op: a `GtkPrintOperation`
- * @unit: the unit to use
- *
- * Sets up the transformation for the cairo context obtained from
- * `GtkPrintContext` in such a way that distances are measured in
- * units of @unit.
- */
-void
-gtk_print_operation_set_unit (GtkPrintOperation *op,
-                             GtkUnit            unit)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  if (priv->unit != unit)
-    {
-      priv->unit = unit;
-
-      g_object_notify (G_OBJECT (op), "unit");
-    }
-}
-
-/**
- * gtk_print_operation_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
- * @op: a `GtkPrintOperation`
- * @track_status: %TRUE to track status after printing
- *
- * If track_status is %TRUE, the print operation 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_operation_set_track_print_status (GtkPrintOperation  *op,
-                                           gboolean            track_status)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  if (priv->track_print_status != track_status)
-    {
-      priv->track_print_status = track_status;
-
-      g_object_notify (G_OBJECT (op), "track-print-status");
-    }
-}
-
-void
-_gtk_print_operation_set_status (GtkPrintOperation *op,
-                                GtkPrintStatus     status,
-                                const char        *string)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  static const char *status_strs[] = {
-    NC_("print operation status", "Initial state"),
-    NC_("print operation status", "Preparing to print"),
-    NC_("print operation status", "Generating data"),
-    NC_("print operation status", "Sending data"),
-    NC_("print operation status", "Waiting"),
-    NC_("print operation status", "Blocking on issue"),
-    NC_("print operation status", "Printing"),
-    NC_("print operation status", "Finished"),
-    NC_("print operation status", "Finished with error")
-  };
-
-  if (status > GTK_PRINT_STATUS_FINISHED_ABORTED)
-    status = GTK_PRINT_STATUS_FINISHED_ABORTED;
-
-  if (string == NULL)
-    string = g_dpgettext2 (GETTEXT_PACKAGE, "print operation status", status_strs[status]);
-  
-  if (priv->status == status &&
-      strcmp (string, priv->status_string) == 0)
-    return;
-  
-  g_free (priv->status_string);
-  priv->status_string = g_strdup (string);
-  priv->status = status;
-
-  g_object_notify (G_OBJECT (op), "status");
-  g_object_notify (G_OBJECT (op), "status-string");
-
-  g_signal_emit (op, signals[STATUS_CHANGED], 0);
-}
-
-
-/**
- * gtk_print_operation_get_status: (attributes org.gtk.Method.get_property=status)
- * @op: a `GtkPrintOperation`
- *
- * Returns the status of the print operation.
- *
- * Also see [method@Gtk.PrintOperation.get_status_string].
- *
- * Returns: the status of the print operation
- */
-GtkPrintStatus
-gtk_print_operation_get_status (GtkPrintOperation *op)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
-                        GTK_PRINT_STATUS_FINISHED_ABORTED);
-
-  return op->priv->status;
-}
-
-/**
- * gtk_print_operation_get_status_string: (attributes org.gtk.Method.get_property=status-string)
- * @op: a `GtkPrintOperation`
- *
- * Returns a string representation of the status of the
- * print operation.
- *
- * The string is translated and suitable for displaying
- * the print status e.g. in a `GtkStatusbar`.
- *
- * Use [method@Gtk.PrintOperation.get_status] to obtain
- * a status value that is suitable for programmatic use.
- *
- * Returns: a string representation of the status
- *    of the print operation
- */
-const char *
-gtk_print_operation_get_status_string (GtkPrintOperation *op)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
-
-  return op->priv->status_string;
-}
-
-/**
- * gtk_print_operation_is_finished:
- * @op: a `GtkPrintOperation`
- *
- * A convenience function to find out if the print operation
- * is finished.
- *
- * a print operation is finished if its status is either
- * %GTK_PRINT_STATUS_FINISHED or %GTK_PRINT_STATUS_FINISHED_ABORTED.
- *
- * Note: when you enable print status tracking the print operation
- * can be in a non-finished state even after done has been called, as
- * the operation status then tracks the print job status on the printer.
- *
- * Returns: %TRUE, if the print operation is finished.
- */
-gboolean
-gtk_print_operation_is_finished (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE);
-
-  return
-    priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED ||
-    priv->status == GTK_PRINT_STATUS_FINISHED;
-}
-
-/**
- * gtk_print_operation_set_show_progress: (attributes org.gtk.Method.set_property=show-progress)
- * @op: a `GtkPrintOperation`
- * @show_progress: %TRUE to show a progress dialog
- *
- * If @show_progress is %TRUE, the print operation will show
- * a progress dialog during the print operation.
- */
-void
-gtk_print_operation_set_show_progress (GtkPrintOperation  *op,
-                                      gboolean            show_progress)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  show_progress = show_progress != FALSE;
-
-  if (priv->show_progress != show_progress)
-    {
-      priv->show_progress = show_progress;
-
-      g_object_notify (G_OBJECT (op), "show-progress");
-    }
-}
-
-/**
- * gtk_print_operation_set_allow_async: (attributes org.gtk.Method.set_property=allow-async)
- * @op: a `GtkPrintOperation`
- * @allow_async: %TRUE to allow asynchronous operation
- *
- * Sets whether gtk_print_operation_run() may return
- * before the print operation is completed.
- *
- * Note that some platforms may not allow asynchronous
- * operation.
- */
-void
-gtk_print_operation_set_allow_async (GtkPrintOperation  *op,
-                                    gboolean            allow_async)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  allow_async = allow_async != FALSE;
-
-  if (priv->allow_async != allow_async)
-    {
-      priv->allow_async = allow_async;
-
-      g_object_notify (G_OBJECT (op), "allow-async");
-    }
-}
-
-
-/**
- * gtk_print_operation_set_custom_tab_label: (attributes org.gtk.Method.set_property=custom-tab-label)
- * @op: a `GtkPrintOperation`
- * @label: (nullable): the label to use, or %NULL to use the default label
- *
- * Sets the label for the tab holding custom widgets.
- */
-void
-gtk_print_operation_set_custom_tab_label (GtkPrintOperation  *op,
-                                         const char         *label)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  g_free (priv->custom_tab_label);
-  priv->custom_tab_label = g_strdup (label);
-
-  g_object_notify (G_OBJECT (op), "custom-tab-label");
-}
-
-
-/**
- * gtk_print_operation_set_export_filename: (attributes org.gtk.Method.set_property=export-filename)
- * @op: a `GtkPrintOperation`
- * @filename: (type filename): the filename for the exported file
- *
- * Sets up the `GtkPrintOperation` to generate a file instead
- * of showing the print dialog.
- *
- * The intended use of this function is for implementing
- * “Export to PDF” actions. Currently, PDF is the only supported
- * format.
- *
- * “Print to PDF” support is independent of this and is done
- * by letting the user pick the “Print to PDF” item from the list
- * of printers in the print dialog.
- */
-void
-gtk_print_operation_set_export_filename (GtkPrintOperation *op,
-                                        const char        *filename)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  g_free (priv->export_filename);
-  priv->export_filename = g_strdup (filename);
-
-  g_object_notify (G_OBJECT (op), "export-filename");
-}
-
-/* Creates the initial page setup used for printing unless the
- * app overrides this on a per-page basis using request_page_setup.
- *
- * Data is taken from, in order, if existing:
- *
- * PrintSettings returned from the print dialog
- *  (initial dialog values are set from default_page_setup
- *   if unset in app specified print_settings)
- * default_page_setup
- * per-locale default setup
- */
-static GtkPageSetup *
-create_page_setup (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  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;
-}
-
-static void 
-pdf_start_page (GtkPrintOperation *op,
-               GtkPrintContext   *print_context,
-               GtkPageSetup      *page_setup)
-{
-  cairo_surface_t *surface = op->priv->platform_data;
-  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 void
-pdf_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
-pdf_end_run (GtkPrintOperation *op,
-            gboolean           wait,
-            gboolean           cancelled)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  cairo_surface_t *surface = priv->platform_data;
-
-  cairo_surface_finish (surface);
-  cairo_surface_destroy (surface);
-
-  priv->platform_data = NULL;
-  priv->free_platform_data = NULL;
-}
-
-static GtkPrintOperationResult
-run_pdf (GtkPrintOperation  *op,
-        GtkWindow          *parent,
-        gboolean           *do_print)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  GtkPageSetup *page_setup;
-  cairo_surface_t *surface;
-  cairo_t *cr;
-  double width, height;
-  
-  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);
-
-  /* This will be overwritten later by the non-default size, but
-     we need to pass some size: */
-  width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
-  height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
-  g_object_unref (page_setup);
-  
-  surface = cairo_pdf_surface_create (priv->export_filename,
-                                     width, height);
-  if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
-    {
-      g_set_error_literal (&priv->error,
-                           GTK_PRINT_ERROR,
-                           GTK_PRINT_ERROR_GENERAL,
-                           cairo_status_to_string (cairo_surface_status (surface)));
-      *do_print = FALSE;
-      return GTK_PRINT_OPERATION_RESULT_ERROR;
-    }
-
-  /* this would crash on a nil surface */
-  cairo_surface_set_fallback_resolution (surface, 300, 300);
-
-  priv->platform_data = surface;
-  priv->free_platform_data = (GDestroyNotify) cairo_surface_destroy;
-
-  cr = cairo_create (surface);
-  gtk_print_context_set_cairo_context (op->priv->print_context,
-                                      cr, 72, 72);
-  cairo_destroy (cr);
-
-  
-  priv->print_pages = GTK_PRINT_PAGES_ALL;
-  priv->page_ranges = NULL;
-  priv->num_page_ranges = 0;
-
-  priv->manual_num_copies = 1;
-  priv->manual_collation = FALSE;
-  priv->manual_reverse = FALSE;
-  priv->manual_page_set = GTK_PAGE_SET_ALL;
-  priv->manual_scale = 1.0;
-  priv->manual_orientation = FALSE;
-  priv->manual_number_up = 1;
-  priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
-  
-  *do_print = TRUE;
-  
-  priv->start_page = pdf_start_page;
-  priv->end_page = pdf_end_page;
-  priv->end_run = pdf_end_run;
-  
-  return GTK_PRINT_OPERATION_RESULT_APPLY; 
-}
-
-
-static void
-clamp_page_ranges (PrintPagesData *data)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-  int                       num_of_correct_ranges;
-  int                       i;
-
-  num_of_correct_ranges = 0;
-
-  for (i = 0; i < data->num_ranges; i++)
-    if ((data->ranges[i].start >= 0) &&
-        (data->ranges[i].start < priv->nr_of_pages) &&
-        (data->ranges[i].end >= 0) &&
-        (data->ranges[i].end < priv->nr_of_pages))
-      {
-        data->ranges[num_of_correct_ranges] = data->ranges[i];
-        num_of_correct_ranges++;
-      }
-    else if ((data->ranges[i].start >= 0) &&
-             (data->ranges[i].start < priv->nr_of_pages) &&
-             (data->ranges[i].end >= priv->nr_of_pages))
-      {
-        data->ranges[i].end = priv->nr_of_pages - 1;
-        data->ranges[num_of_correct_ranges] = data->ranges[i];
-        num_of_correct_ranges++;
-      }
-    else if ((data->ranges[i].end >= 0) &&
-             (data->ranges[i].end < priv->nr_of_pages) &&
-             (data->ranges[i].start < 0))
-      {
-        data->ranges[i].start = 0;
-        data->ranges[num_of_correct_ranges] = data->ranges[i];
-        num_of_correct_ranges++;
-      }
-
-  data->num_ranges = num_of_correct_ranges;
-}
-
-static void
-increment_page_sequence (PrintPagesData *data)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-  int inc;
-
-  if (data->total == -1)
-    {
-      data->total = 0;
-      return;
-    }
-
-  /* check whether we reached last position */
-  if (priv->page_position == data->last_position &&
-      !(data->collated_copies > 1 && data->collated < (data->collated_copies - 1)))
-    {
-      if (data->uncollated_copies > 1 && data->uncollated < (data->uncollated_copies - 1))
-        {
-          priv->page_position = data->first_position;
-          data->sheet = data->first_sheet;
-          data->uncollated++;
-        }
-      else
-        {
-          data->done = TRUE;
-         return;
-        }
-    }
-  else
-    {
-      if (priv->manual_reverse)
-        inc = -1;
-      else
-        inc = 1;
-
-      /* changing sheet */
-      if (priv->manual_number_up < 2 ||
-          (priv->page_position + 1) % priv->manual_number_up == 0 ||
-          priv->page_position == data->last_position ||
-          priv->page_position == priv->nr_of_pages_to_print - 1)
-        {
-          /* check whether to print the same sheet again */
-          if (data->collated_copies > 1)
-            {
-              if (data->collated < (data->collated_copies - 1))
-                {
-                  data->collated++;
-                  data->total++;
-                  priv->page_position = data->sheet * priv->manual_number_up;
-
-                  if (priv->page_position < 0 ||
-                      priv->page_position >= priv->nr_of_pages_to_print ||
-                      data->sheet < 0 ||
-                      data->sheet >= data->num_of_sheets)
-                   {
-                      data->done = TRUE;
-                     return;
-                   }
-                  else
-                    data->page = data->pages[priv->page_position];
-
-                  return;
-                }
-              else
-                data->collated = 0;
-            }
-
-          if (priv->manual_page_set == GTK_PAGE_SET_ODD ||
-              priv->manual_page_set == GTK_PAGE_SET_EVEN)
-            data->sheet += 2 * inc;
-          else
-            data->sheet += inc;
-
-          priv->page_position = data->sheet * priv->manual_number_up;
-        }
-      else
-        priv->page_position += 1;
-    }
-
-  /* general check */
-  if (priv->page_position < 0 ||
-      priv->page_position >= priv->nr_of_pages_to_print ||
-      data->sheet < 0 ||
-      data->sheet >= data->num_of_sheets)
-    {
-      data->done = TRUE;
-      return;
-    }
-  else
-    data->page = data->pages[priv->page_position];
-
-  data->total++;
-}
-
-static void
-print_pages_idle_done (gpointer user_data)
-{
-  PrintPagesData *data = (PrintPagesData*)user_data;
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-
-  priv->print_pages_idle_id = 0;
-
-  if (priv->show_progress_timeout_id > 0)
-    {
-      g_source_remove (priv->show_progress_timeout_id);
-      priv->show_progress_timeout_id = 0;
-    }
-  if (data->progress)
-    gtk_window_destroy (GTK_WINDOW (data->progress));
-
-  if (priv->rloop && !data->is_preview) 
-    g_main_loop_quit (priv->rloop);
-
-  if (!data->is_preview)
-    {
-      GtkPrintOperationResult result;
-
-      if (priv->error)
-        result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      else if (priv->cancelled)
-        result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-      else
-        result = GTK_PRINT_OPERATION_RESULT_APPLY;
-
-      g_signal_emit (data->op, signals[DONE], 0, result);
-    }
-  
-  g_object_unref (data->op);
-  g_free (data->pages);
-  g_free (data);
-}
-
-static void
-update_progress (PrintPagesData *data)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-  char *text = NULL;
-
-  if (data->progress)
-    {
-      if (priv->status == GTK_PRINT_STATUS_PREPARING)
-       {
-         if (priv->nr_of_pages_to_print > 0)
-           text = g_strdup_printf (_("Preparing %d"), priv->nr_of_pages_to_print);
-         else
-           text = g_strdup (_("Preparing"));
-       }
-      else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
-       text = g_strdup_printf (_("Printing %d"), data->total);
-      
-      if (text)
-       {
-         g_object_set (data->progress, "text", text, NULL);
-         g_free (text);
-       }
-    }
- }
-
-/**
- * gtk_print_operation_set_defer_drawing:
- * @op: a `GtkPrintOperation`
- *
- * Sets up the `GtkPrintOperation` to wait for calling of
- * [method@Gtk.PrintOperation.draw_page_finish from application.
- *
- * This can be used for drawing page in another thread.
- *
- * This function must be called in the callback of the
- * [signal@Gtk.PrintOperation::draw-page] signal.
- */
-void
-gtk_print_operation_set_defer_drawing (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING);
-
-  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING;
-}
-
-/**
- * gtk_print_operation_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
- * @op: a `GtkPrintOperation`
- * @embed: %TRUE to embed page setup selection in the `GtkPrintUnixDialog`
- *
- * Embed page size combo box and orientation combo box into page setup page.
- *
- * Selected page setup is stored as default page setup in `GtkPrintOperation`.
- */
-void
-gtk_print_operation_set_embed_page_setup (GtkPrintOperation  *op,
-                                          gboolean            embed)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  embed = embed != FALSE;
-  if (priv->embed_page_setup != embed)
-    {
-      priv->embed_page_setup = embed;
-      g_object_notify (G_OBJECT (op), "embed-page-setup");
-    }
-}
-
-/**
- * gtk_print_operation_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
- * @op: a `GtkPrintOperation`
- *
- * Gets whether page setup selection combos are embedded
- *
- * Returns: whether page setup selection combos are embedded
- */
-gboolean
-gtk_print_operation_get_embed_page_setup (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
-
-  return priv->embed_page_setup;
-}
-
-/**
- * gtk_print_operation_draw_page_finish:
- * @op: a `GtkPrintOperation`
- *
- * Signal that drawing of particular page is complete.
- *
- * It is called after completion of page drawing (e.g. drawing
- * in another thread). If [method@Gtk.PrintOperation.set_defer_drawing]
- * was called before, then this function has to be called by application.
- * Otherwise it is called by GTK itself.
- */
-void
-gtk_print_operation_draw_page_finish (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  GtkPageSetup *page_setup;
-  GtkPrintContext *print_context;
-  cairo_t *cr;
-  
-  print_context = priv->print_context;
-  page_setup = gtk_print_context_get_page_setup (print_context);
-
-  cr = gtk_print_context_get_cairo_context (print_context);
-
-  priv->end_page (op, print_context);
-  
-  cairo_restore (cr);
-
-  g_object_unref (page_setup);
-
-  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
-}
-
-static void
-common_render_page (GtkPrintOperation *op,
-                   int                page_nr)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  GtkPageSetup *page_setup;
-  GtkPrintContext *print_context;
-  cairo_t *cr;
-
-  print_context = priv->print_context;
-  
-  page_setup = create_page_setup (op);
-  
-  g_signal_emit (op, signals[REQUEST_PAGE_SETUP], 0, 
-                print_context, page_nr, page_setup);
-  
-  _gtk_print_context_set_page_setup (print_context, page_setup);
-  
-  priv->start_page (op, print_context, page_setup);
-  
-  cr = gtk_print_context_get_cairo_context (print_context);
-  
-  cairo_save (cr);
-  
-  if (priv->manual_orientation)
-    _gtk_print_context_rotate_according_to_orientation (print_context);
-  else
-    _gtk_print_context_reverse_according_to_orientation (print_context);
-
-  if (priv->manual_number_up <= 1)
-    {
-      if (!priv->use_full_page)
-        _gtk_print_context_translate_into_margin (print_context);
-      if (priv->manual_scale != 1.0)
-        cairo_scale (cr,
-                     priv->manual_scale,
-                     priv->manual_scale);
-    }
-  else
-    {
-      GtkPageOrientation  orientation;
-      double              paper_width, paper_height;
-      double              page_width, page_height;
-      double              context_width, context_height;
-      double              bottom_margin, top_margin, left_margin, right_margin;
-      double              x_step, y_step;
-      double              x_scale, y_scale, scale;
-      double              horizontal_offset = 0.0, vertical_offset = 0.0;
-      int                 columns, rows, x, y, tmp_length;
-
-      page_setup = gtk_print_context_get_page_setup (print_context);
-      orientation = gtk_page_setup_get_orientation (page_setup);
-
-      top_margin = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_POINTS);
-      bottom_margin = gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_POINTS);
-      left_margin = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_POINTS);
-      right_margin = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_POINTS);
-
-      paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
-      paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
-
-      context_width = gtk_print_context_get_width (print_context);
-      context_height = gtk_print_context_get_height (print_context);
-
-      if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-          orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-        {
-          page_width = paper_width - (left_margin + right_margin);
-          page_height = paper_height - (top_margin + bottom_margin);
-        }
-      else
-        {
-          page_width = paper_width - (top_margin + bottom_margin);
-          page_height = paper_height - (left_margin + right_margin);
-        }
-
-      if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
-          orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
-        cairo_translate (cr, left_margin, top_margin);
-      else
-        cairo_translate (cr, top_margin, left_margin);
-
-      switch (priv->manual_number_up)
-        {
-          default:
-            columns = 1;
-            rows = 1;
-            break;
-          case 2:
-            columns = 2;
-            rows = 1;
-            break;
-          case 4:
-            columns = 2;
-            rows = 2;
-            break;
-          case 6:
-            columns = 3;
-            rows = 2;
-            break;
-          case 9:
-            columns = 3;
-            rows = 3;
-            break;
-          case 16:
-            columns = 4;
-            rows = 4;
-            break;
-        }
-
-      if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
-          orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
-        {
-          tmp_length = columns;
-          columns = rows;
-          rows = tmp_length;
-        }
-
-      switch (priv->manual_number_up_layout)
-        {
-          case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
-            x = priv->page_position % columns;
-            y = (priv->page_position / columns) % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
-            x = priv->page_position % columns;
-            y = rows - 1 - (priv->page_position / columns) % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
-            x = columns - 1 - priv->page_position % columns;
-            y = (priv->page_position / columns) % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
-            x = columns - 1 - priv->page_position % columns;
-            y = rows - 1 - (priv->page_position / columns) % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
-            x = (priv->page_position / rows) % columns;
-            y = priv->page_position % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
-            x = columns - 1 - (priv->page_position / rows) % columns;
-            y = priv->page_position % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
-            x = (priv->page_position / rows) % columns;
-            y = rows - 1 - priv->page_position % rows;
-            break;
-          case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
-            x = columns - 1 - (priv->page_position / rows) % columns;
-            y = rows - 1 - priv->page_position % rows;
-            break;
-          default:
-            g_assert_not_reached();
-            x = 0;
-            y = 0;
-        }
-
-      if (priv->manual_number_up == 4 || priv->manual_number_up == 9 || priv->manual_number_up == 16)
-        {
-          x_scale = page_width / (columns * paper_width);
-          y_scale = page_height / (rows * paper_height);
-
-          scale = x_scale < y_scale ? x_scale : y_scale;
-
-          x_step = paper_width * (x_scale / scale);
-          y_step = paper_height * (y_scale / scale);
-
-          if ((left_margin + right_margin) > 0)
-            {
-              horizontal_offset = left_margin * (x_step - context_width) / (left_margin + right_margin);
-              vertical_offset = top_margin * (y_step - context_height) / (top_margin + bottom_margin);
-            }
-          else
-            {
-              horizontal_offset = (x_step - context_width) / 2.0;
-              vertical_offset = (y_step - context_height) / 2.0;
-            }
-
-          cairo_scale (cr, scale, scale);
-
-          cairo_translate (cr,
-                           x * x_step + horizontal_offset,
-                           y * y_step + vertical_offset);
-
-          if (priv->manual_scale != 1.0)
-            cairo_scale (cr, priv->manual_scale, priv->manual_scale);
-        }
-
-      if (priv->manual_number_up == 2 || priv->manual_number_up == 6)
-        {
-          x_scale = page_height / (columns * paper_width);
-          y_scale = page_width / (rows * paper_height);
-
-          scale = x_scale < y_scale ? x_scale : y_scale;
-
-          horizontal_offset = (paper_width * (x_scale / scale) - paper_width) / 2.0 * columns;
-          vertical_offset = (paper_height * (y_scale / scale) - paper_height) / 2.0 * rows;
-
-          if (!priv->use_full_page)
-            {
-              horizontal_offset -= right_margin;
-              vertical_offset += top_margin;
-            }
-
-          cairo_scale (cr, scale, scale);
-
-          cairo_translate (cr,
-                           y * paper_height + vertical_offset,
-                           (columns - x) * paper_width + horizontal_offset);
-
-          if (priv->manual_scale != 1.0)
-            cairo_scale (cr, priv->manual_scale, priv->manual_scale);
-
-          cairo_rotate (cr, - G_PI / 2);
-        }
-    }
-  
-  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DRAWING;
-
-  g_signal_emit (op, signals[DRAW_PAGE], 0, 
-                print_context, page_nr);
-
-  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING)
-    gtk_print_operation_draw_page_finish (op);
-}
-
-static void
-prepare_data (PrintPagesData *data)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-  GtkPageSetup             *page_setup;
-  gboolean                  paginated = FALSE;
-  int                       i, j, counter;
-
-  if (priv->manual_collation)
-    {
-      data->uncollated_copies = priv->manual_num_copies;
-      data->collated_copies = 1;
-    }
-  else
-    {
-      data->uncollated_copies = 1;
-      data->collated_copies = priv->manual_num_copies;
-    }
-
-  if (!data->initialized)
-    {
-      data->initialized = TRUE;
-      page_setup = create_page_setup (data->op);
-      _gtk_print_context_set_page_setup (priv->print_context,
-                                         page_setup);
-      g_object_unref (page_setup);
-
-      g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
-
-      return;
-    }
-
-  g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
-  if (!paginated)
-    return;
-
-  /* Initialize parts of PrintPagesData that depend on nr_of_pages
-   */
-  if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
-    {
-      if (priv->page_ranges == NULL) 
-        {
-          g_warning ("no pages to print");
-          priv->cancelled = TRUE;
-          return;
-        }
-      data->ranges = priv->page_ranges;
-      data->num_ranges = priv->num_page_ranges;
-      for (i = 0; i < data->num_ranges; i++)
-        if (data->ranges[i].end == -1 || 
-            data->ranges[i].end >= priv->nr_of_pages)
-          data->ranges[i].end = priv->nr_of_pages - 1;
-    }
-  else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
-   priv->current_page != -1)
-    {
-      data->ranges = &data->one_range;
-      data->num_ranges = 1;
-      data->ranges[0].start = priv->current_page;
-      data->ranges[0].end = priv->current_page;
-    }
-  else
-    {
-      data->ranges = &data->one_range;
-      data->num_ranges = 1;
-      data->ranges[0].start = 0;
-      data->ranges[0].end = priv->nr_of_pages - 1;
-    }
-
-  clamp_page_ranges (data);
-
-  if (data->num_ranges < 1) 
-    {
-      priv->cancelled = TRUE;
-      return;
-    }
-
-  priv->nr_of_pages_to_print = 0;
-  for (i = 0; i < data->num_ranges; i++)
-    priv->nr_of_pages_to_print += data->ranges[i].end - data->ranges[i].start + 1;
-
-  data->pages = g_new (int, priv->nr_of_pages_to_print);
-  counter = 0;
-  for (i = 0; i < data->num_ranges; i++)
-    for (j = data->ranges[i].start; j <= data->ranges[i].end; j++)
-      {
-        data->pages[counter] = j;
-        counter++;
-      }
-
-  data->total = -1;
-  data->collated = 0;
-  data->uncollated = 0;
-
-  if (priv->manual_number_up > 1)
-    {
-      if (priv->nr_of_pages_to_print % priv->manual_number_up == 0)
-        data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up;
-      else
-        data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up + 1;
-    }
-  else
-    data->num_of_sheets = priv->nr_of_pages_to_print;
-
-  if (priv->manual_reverse)
-    {
-      /* data->sheet is 0-based */
-      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
-        data->sheet = (data->num_of_sheets - 1) - (data->num_of_sheets - 1) % 2;
-      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
-        data->sheet = (data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2);
-      else
-        data->sheet = data->num_of_sheets - 1;
-    }
-  else
-    {
-      /* data->sheet is 0-based */
-      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
-        data->sheet = 0;
-      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
-        {
-          if (data->num_of_sheets > 1)
-            data->sheet = 1;
-          else
-            data->sheet = -1;
-        }
-      else
-        data->sheet = 0;
-    }
-
-  priv->page_position = data->sheet * priv->manual_number_up;
-
-  if (priv->page_position < 0 || priv->page_position >= priv->nr_of_pages_to_print)
-    {
-      priv->cancelled = TRUE;
-      return;
-    }
-
-  data->page = data->pages[priv->page_position];
-  data->first_position = priv->page_position;
-  data->first_sheet = data->sheet;
-
-  if (priv->manual_reverse)
-    {
-      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
-        data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
-      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
-        data->last_position = MIN (2 * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
-      else
-        data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
-    }
-  else
-    {
-      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
-        data->last_position = MIN (((data->num_of_sheets - 1) - ((data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
-      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
-        data->last_position = MIN (((data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
-      else
-        data->last_position = priv->nr_of_pages_to_print - 1;
-    }
-
-
-  _gtk_print_operation_set_status (data->op, 
-                                   GTK_PRINT_STATUS_GENERATING_DATA, 
-                                   NULL);
-}
-
-static gboolean
-print_pages_idle (gpointer user_data)
-{
-  PrintPagesData *data = (PrintPagesData*)user_data;
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
-  gboolean done = FALSE;
-
-  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
-    {
-      if (priv->status == GTK_PRINT_STATUS_PREPARING)
-        {
-          prepare_data (data);
-          goto out;
-        }
-
-      if (data->is_preview && !priv->cancelled)
-        {
-          done = TRUE;
-
-          g_signal_emit_by_name (data->op, "ready", priv->print_context);
-          goto out;
-        }
-
-      increment_page_sequence (data);
-
-      if (!data->done)
-        common_render_page (data->op, data->page);
-      else
-        done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
-
- out:
-
-      if (priv->cancelled)
-        {
-          _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-
-          data->is_preview = FALSE;
-          done = TRUE;
-        }
-
-      if (done && !data->is_preview)
-        {
-          g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
-          priv->end_run (data->op, priv->is_sync, priv->cancelled);
-        }
-
-      update_progress (data);
-    }
-
-  return !done;
-}
-  
-static void
-handle_progress_response (GtkWidget *dialog, 
-                         int        response,
-                         gpointer   data)
-{
-  GtkPrintOperation *op = (GtkPrintOperation *)data;
-
-  gtk_widget_set_visible (dialog, FALSE);
-  gtk_print_operation_cancel (op);
-}
-
-static gboolean
-show_progress_timeout (PrintPagesData *data)
-{
-  gtk_window_present (GTK_WINDOW (data->progress));
-
-  data->op->priv->show_progress_timeout_id = 0;
-
-  return FALSE;
-}
-
-static void
-print_pages (GtkPrintOperation       *op,
-            GtkWindow               *parent,
-            gboolean                 do_print,
-            GtkPrintOperationResult  result)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  PrintPagesData *data;
-  if (!do_print) 
-    {
-      GtkPrintOperationResult tmp_result;
-
-      _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-
-      if (priv->error)
-        tmp_result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      else if (priv->cancelled)
-        tmp_result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-      else
-        tmp_result = result;
-
-      g_signal_emit (op, signals[DONE], 0, tmp_result);
-
-      return;
-  }
-  
-  _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL);  
-
-  data = g_new0 (PrintPagesData, 1);
-  data->op = g_object_ref (op);
-  data->is_preview = (priv->action == GTK_PRINT_OPERATION_ACTION_PREVIEW);
-
-  if (priv->show_progress)
-    {
-      GtkWidget *progress;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      progress = gtk_message_dialog_new (parent, 0,
-                                         GTK_MESSAGE_OTHER,
-                                         GTK_BUTTONS_CANCEL,
-                                         _("Preparing"));
-G_GNUC_END_IGNORE_DEPRECATIONS
-      g_signal_connect (progress, "response",
-                        G_CALLBACK (handle_progress_response), op);
-
-      priv->show_progress_timeout_id =
-        g_timeout_add (SHOW_PROGRESS_TIME,
-                       (GSourceFunc) show_progress_timeout,
-                       data);
-      gdk_source_set_static_name_by_id (priv->show_progress_timeout_id, "[gtk] show_progress_timeout");
-
-      data->progress = progress;
-    }
-
-  if (data->is_preview)
-    {
-      gboolean handled;
-      
-      g_signal_emit_by_name (op, "preview",
-                            GTK_PRINT_OPERATION_PREVIEW (op),
-                            priv->print_context,
-                            parent,
-                            &handled);
-
-      if (!handled)
-        {
-          GtkWidget *error_dialog;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-          error_dialog = gtk_message_dialog_new (parent,
-                                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                                 GTK_MESSAGE_ERROR,
-                                                 GTK_BUTTONS_OK,
-                                                 _("Error creating print preview"));
-
-          gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
-                                                    _("The most probable reason is that a temporary file could not be created."));
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-          if (parent && gtk_window_has_group (parent))
-            gtk_window_group_add_window (gtk_window_get_group (parent),
-                                         GTK_WINDOW (error_dialog));
-
-          g_signal_connect (error_dialog, "response",
-                            G_CALLBACK (gtk_window_destroy), NULL);
-
-          gtk_window_present (GTK_WINDOW (error_dialog));
-
-          print_pages_idle_done (data);
-
-          return;
-        }
-
-      if (gtk_print_context_get_cairo_context (priv->print_context) == NULL)
-        {
-          /* Programmer error */
-          g_error ("You must set a cairo context on the print context");
-        }
-      
-      priv->start_page = preview_start_page;
-      priv->end_page = preview_end_page;
-      priv->end_run = preview_end_run;
-
-      priv->print_pages = gtk_print_settings_get_print_pages (priv->print_settings);
-      priv->page_ranges = gtk_print_settings_get_page_ranges (priv->print_settings,
-                                                             &priv->num_page_ranges);
-      priv->manual_num_copies = 1;
-      priv->manual_collation = FALSE;
-      priv->manual_reverse = gtk_print_settings_get_reverse (priv->print_settings);
-      priv->manual_page_set = gtk_print_settings_get_page_set (priv->print_settings);
-      priv->manual_scale = gtk_print_settings_get_scale (priv->print_settings) / 100.0;
-      priv->manual_orientation = FALSE;
-      priv->manual_number_up = gtk_print_settings_get_number_up (priv->print_settings);
-      priv->manual_number_up_layout = gtk_print_settings_get_number_up_layout (priv->print_settings);
-    }
-  
-  priv->print_pages_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
-                                               print_pages_idle,
-                                               data,
-                                               print_pages_idle_done);
-  gdk_source_set_static_name_by_id (priv->print_pages_idle_id, "[gtk] print_pages_idle");
-  
-  /* Recursive main loop to make sure we don't exit  on sync operations  */
-  if (priv->is_sync)
-    {
-      priv->rloop = g_main_loop_new (NULL, FALSE);
-
-      g_object_ref (op);
-
-      g_main_loop_run (priv->rloop);
-      g_main_loop_unref (priv->rloop);
-      priv->rloop = NULL;
-
-      g_object_unref (op);
-    }
-}
-
-/**
- * gtk_print_operation_get_error:
- * @op: a `GtkPrintOperation`
- * @error: return location for the error
- *
- * Call this when the result of a print operation is
- * %GTK_PRINT_OPERATION_RESULT_ERROR.
- *
- * It can be called either after [method@Gtk.PrintOperation.run]
- * returns, or in the [signal@Gtk.PrintOperation::done] signal
- * handler.
- *
- * The returned `GError` will contain more details on what went wrong.
- */
-void
-gtk_print_operation_get_error (GtkPrintOperation  *op,
-                              GError            **error)
-{
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  
-  g_propagate_error (error, op->priv->error);
-
-  op->priv->error = NULL;
-}
-
-
-/**
- * gtk_print_operation_run:
- * @op: a `GtkPrintOperation`
- * @action: the action to start
- * @parent: (nullable): Transient parent of the dialog
- * @error: (nullable): Return location for errors
- *
- * Runs the print operation.
- *
- * Normally that this function does not return until the rendering
- * of all pages is complete. You can connect to the
- * [signal@Gtk.PrintOperation::status-changed] signal on @op to obtain
- * some information about the progress of the print operation.
- *
- * Furthermore, it may use a recursive mainloop to show the print dialog.
- *
- * If you set the [Gtk.PrintOperation:allow-async] property, the operation
- * will run asynchronously if this is supported on the platform. The
- * [signal@Gtk.PrintOperation::done] signal will be emitted with the result
- * of the operation when the it is done (i.e. when the dialog is canceled,
- * or when the print succeeds or fails).
- *
- * ```c
- * if (settings != NULL)
- *   gtk_print_operation_set_print_settings (print, settings);
- *
- * if (page_setup != NULL)
- *   gtk_print_operation_set_default_page_setup (print, page_setup);
- *
- * g_signal_connect (print, "begin-print",
- *                   G_CALLBACK (begin_print), &data);
- * g_signal_connect (print, "draw-page",
- *                   G_CALLBACK (draw_page), &data);
- *
- * res = gtk_print_operation_run (print,
- *                                GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- *                                parent,
- *                                &error);
- *
- * if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
- *  {
- *    error_dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
- *                                          GTK_DIALOG_DESTROY_WITH_PARENT,
- *                                          GTK_MESSAGE_ERROR,
- *                                          GTK_BUTTONS_CLOSE,
- *                                          "Error printing file:\n%s",
- *                                          error->message);
- *    g_signal_connect (error_dialog, "response",
- *                      G_CALLBACK (gtk_window_destroy), NULL);
- *    gtk_window_present (GTK_WINDOW (error_dialog));
- *    g_error_free (error);
- *  }
- * else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
- *  {
- *    if (settings != NULL)
- *     g_object_unref (settings);
- *    settings = g_object_ref (gtk_print_operation_get_print_settings (print));
- *  }
- * ```
- *
- * Note that gtk_print_operation_run() can only be called once on a
- * given `GtkPrintOperation`.
- *
- * Returns: the result of the print operation. A return value of
- *   %GTK_PRINT_OPERATION_RESULT_APPLY indicates that the printing was
- *   completed successfully. In this case, it is a good idea to obtain
- *   the used print settings with
- *   [method@Gtk.PrintOperation.get_print_settings]
- *   and store them for reuse with the next print operation. A value of
- *   %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS means the operation is running
- *   asynchronously, and will emit the [signal@Gtk.PrintOperation::done]
- *   signal when done.
- */
-GtkPrintOperationResult
-gtk_print_operation_run (GtkPrintOperation        *op,
-                        GtkPrintOperationAction   action,
-                        GtkWindow                *parent,
-                        GError                  **error)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-  GtkPrintOperationResult result;
-  GtkPageSetup *page_setup;
-  gboolean do_print;
-  gboolean run_print_pages;
-  
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
-                        GTK_PRINT_OPERATION_RESULT_ERROR);
-  g_return_val_if_fail (op->priv->status == GTK_PRINT_STATUS_INITIAL,
-                        GTK_PRINT_OPERATION_RESULT_ERROR);
-  
-  run_print_pages = TRUE;
-  do_print = FALSE;
-  priv->error = NULL;
-  priv->action = action;
-
-  if (priv->print_settings == NULL)
-    priv->print_settings = gtk_print_settings_new ();
-  
-  if (action == GTK_PRINT_OPERATION_ACTION_EXPORT)
-    {
-      /* note: if you implement async EXPORT, update the docs
-       * docs for the allow-async property.
-       */
-      priv->is_sync = TRUE;
-      g_return_val_if_fail (priv->export_filename != NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
-      result = run_pdf (op, parent, &do_print);
-    }
-  else if (action == GTK_PRINT_OPERATION_ACTION_PREVIEW)
-    {
-      priv->is_sync = !priv->allow_async;
-      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;
-      result = priv->is_sync ? GTK_PRINT_OPERATION_RESULT_APPLY : GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
-    }
-#ifndef G_OS_WIN32
-  else if (priv->allow_async)
-    {
-      priv->is_sync = FALSE;
-      _gtk_print_operation_platform_backend_run_dialog_async (op,
-                                                             action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
-                                                             parent,
-                                                             print_pages);
-      result = GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
-      run_print_pages = FALSE; /* print_pages is called asynchronously from dialog */
-    }
-#endif
-  else
-    {
-      priv->is_sync = TRUE;
-      result = _gtk_print_operation_platform_backend_run_dialog (op, 
-                                                                action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
-                                                                parent,
-                                                                &do_print);
-    }
-
-  /* To ensure that priv is still valid after print_pages () */
-  g_object_ref (op);
-
-  if (run_print_pages)
-    print_pages (op, parent, do_print, result);
-
-  if (priv->error)
-    {
-      if (error)
-        *error = g_error_copy (priv->error);
-      result = GTK_PRINT_OPERATION_RESULT_ERROR;
-    }
-  else if (priv->cancelled)
-    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
-  g_object_unref (op);
-  return result;
-}
-
-/**
- * gtk_print_operation_cancel:
- * @op: a `GtkPrintOperation`
- *
- * Cancels a running print operation.
- *
- * This function may be called from a [signal@Gtk.PrintOperation::begin-print],
- * [signal@Gtk.PrintOperation::paginate] or [signal@Gtk.PrintOperation::draw-page]
- * signal handler to stop the currently running print operation.
- */
-void
-gtk_print_operation_cancel (GtkPrintOperation *op)
-{
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-  
-  op->priv->cancelled = TRUE;
-}
-
-/**
- * gtk_print_operation_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
- * @op: a `GtkPrintOperation`
- * @support_selection: %TRUE to support selection
- *
- * Sets whether selection is supported by `GtkPrintOperation`.
- */
-void
-gtk_print_operation_set_support_selection (GtkPrintOperation  *op,
-                                           gboolean            support_selection)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  support_selection = support_selection != FALSE;
-  if (priv->support_selection != support_selection)
-    {
-      priv->support_selection = support_selection;
-      g_object_notify (G_OBJECT (op), "support-selection");
-    }
-}
-
-/**
- * gtk_print_operation_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
- * @op: a `GtkPrintOperation`
- *
- * Gets whether the application supports print of selection
- *
- * Returns: whether the application supports print of selection
- */
-gboolean
-gtk_print_operation_get_support_selection (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
-
-  return priv->support_selection;
-}
-
-/**
- * gtk_print_operation_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
- * @op: a `GtkPrintOperation`
- * @has_selection: %TRUE indicates that a selection exists
- *
- * Sets whether there is a selection to print.
- *
- * Application has to set number of pages to which the selection
- * will draw by [method@Gtk.PrintOperation.set_n_pages] in a handler
- * for the [signal@Gtk.PrintOperation::begin-print] signal.
- */
-void
-gtk_print_operation_set_has_selection (GtkPrintOperation  *op,
-                                       gboolean            has_selection)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
-
-  has_selection = has_selection != FALSE;
-  if (priv->has_selection != has_selection)
-    {
-      priv->has_selection = has_selection;
-      g_object_notify (G_OBJECT (op), "has-selection");
-    }
-}
-
-/**
- * gtk_print_operation_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
- * @op: a `GtkPrintOperation`
- *
- * Gets whether there is a selection.
- *
- * Returns: whether there is a selection
- */
-gboolean
-gtk_print_operation_get_has_selection (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
-
-  return priv->has_selection;
-}
-
-/**
- * gtk_print_operation_get_n_pages_to_print: (attributes org.gtk.Method.get_property=n-pages-to-print)
- * @op: a `GtkPrintOperation`
- *
- * Returns the number of pages that will be printed.
- *
- * Note that this value is set during print preparation phase
- * (%GTK_PRINT_STATUS_PREPARING), so this function should never be
- * called before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
- * You can connect to the [signal@Gtk.PrintOperation::status-changed]
- * signal and call gtk_print_operation_get_n_pages_to_print() when
- * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
- *
- * This is typically used to track the progress of print operation.
- *
- * Returns: the number of pages that will be printed
- */
-int
-gtk_print_operation_get_n_pages_to_print (GtkPrintOperation *op)
-{
-  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
-
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), -1);
-
-  return priv->nr_of_pages_to_print;
-}
diff --git a/gtk/gtkprintoperationpreview.c b/gtk/gtkprintoperationpreview.c
deleted file mode 100644 (file)
index af4ae58..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkprintoperationpreview.c: Abstract print preview interface
- * 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 "print/gtkprintoperationpreview.h"
-#include "gtkmarshalers.h"
-#include "gtkprivate.h"
-
-
-/**
- * GtkPrintOperationPreview:
- *
- * `GtkPrintOperationPreview` is the interface that is used to
- * implement print preview.
- *
- * A `GtkPrintOperationPreview` object is passed to the
- * [signal@Gtk.PrintOperation::preview] signal by
- * [class@Gtk.PrintOperation].
- */
-
-static void gtk_print_operation_preview_base_init (gpointer g_iface);
-
-GType
-gtk_print_operation_preview_get_type (void)
-{
-  static GType print_operation_preview_type = 0;
-
-  if (!print_operation_preview_type)
-    {
-      const GTypeInfo print_operation_preview_info =
-      {
-        sizeof (GtkPrintOperationPreviewIface), /* class_size */
-       gtk_print_operation_preview_base_init,   /* base_init */
-       NULL,           /* base_finalize */
-       NULL,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       0,
-       0,              /* n_preallocs */
-       NULL
-      };
-
-      print_operation_preview_type =
-       g_type_register_static (G_TYPE_INTERFACE, I_("GtkPrintOperationPreview"),
-                               &print_operation_preview_info, 0);
-
-      g_type_interface_add_prerequisite (print_operation_preview_type, G_TYPE_OBJECT);
-    }
-
-  return print_operation_preview_type;
-}
-
-static void
-gtk_print_operation_preview_base_init (gpointer g_iface)
-{
-  static gboolean initialized = FALSE;
-
-  if (!initialized)
-    {
-      unsigned int id;
-
-      /**
-       * GtkPrintOperationPreview::ready:
-       * @preview: the object on which the signal is emitted
-       * @context: the current `GtkPrintContext`
-       *
-       * The ::ready signal gets emitted once per preview operation,
-       * before the first page is rendered.
-       * 
-       * A handler for this signal can be used for setup tasks.
-       */
-      g_signal_new (I_("ready"),
-                   GTK_TYPE_PRINT_OPERATION_PREVIEW,
-                   G_SIGNAL_RUN_LAST,
-                   G_STRUCT_OFFSET (GtkPrintOperationPreviewIface, ready),
-                   NULL, NULL,
-                   NULL,
-                   G_TYPE_NONE, 1,
-                   GTK_TYPE_PRINT_CONTEXT);
-
-      /**
-       * GtkPrintOperationPreview::got-page-size:
-       * @preview: the object on which the signal is emitted
-       * @context: the current `GtkPrintContext`
-       * @page_setup: the `GtkPageSetup` for the current page
-       *
-       * Emitted once for each page that gets rendered to the preview.
-       *
-       * A handler for this signal should update the @context
-       * according to @page_setup and set up a suitable cairo
-       * context, using [method@Gtk.PrintContext.set_cairo_context].
-       */
-      id = g_signal_new (I_("got-page-size"),
-                         GTK_TYPE_PRINT_OPERATION_PREVIEW,
-                         G_SIGNAL_RUN_LAST,
-                         G_STRUCT_OFFSET (GtkPrintOperationPreviewIface, got_page_size),
-                         NULL, NULL,
-                         _gtk_marshal_VOID__OBJECT_OBJECT,
-                         G_TYPE_NONE, 2,
-                         GTK_TYPE_PRINT_CONTEXT,
-                         GTK_TYPE_PAGE_SETUP);
-      g_signal_set_va_marshaller (id,
-                                  GTK_TYPE_PRINT_OPERATION_PREVIEW,
-                                  _gtk_marshal_VOID__OBJECT_OBJECTv);
-
-      initialized = TRUE;
-    }
-}
-
-/**
- * gtk_print_operation_preview_render_page:
- * @preview: a `GtkPrintOperationPreview`
- * @page_nr: the page to render
- *
- * Renders a page to the preview.
- *
- * This is using the print context that was passed to the
- * [signal@Gtk.PrintOperation::preview] handler together
- * with @preview.
- *
- * A custom print preview should use this function to render
- * the currently selected page.
- *
- * Note that this function requires a suitable cairo context to
- * be associated with the print context.
- */
-void    
-gtk_print_operation_preview_render_page (GtkPrintOperationPreview *preview,
-                                        int                       page_nr)
-{
-  g_return_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview));
-
-  GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->render_page (preview,
-                                                               page_nr);
-}
-
-/**
- * gtk_print_operation_preview_end_preview:
- * @preview: a `GtkPrintOperationPreview`
- *
- * Ends a preview.
- *
- * This function must be called to finish a custom print preview.
- */
-void
-gtk_print_operation_preview_end_preview (GtkPrintOperationPreview *preview)
-{
-  g_return_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview));
-
-  GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->end_preview (preview);
-}
-
-/**
- * gtk_print_operation_preview_is_selected:
- * @preview: a `GtkPrintOperationPreview`
- * @page_nr: a page number
- *
- * Returns whether the given page is included in the set of pages that
- * have been selected for printing.
- *
- * Returns: %TRUE if the page has been selected for printing
- */
-gboolean
-gtk_print_operation_preview_is_selected (GtkPrintOperationPreview *preview,
-                                        int                       page_nr)
-{
-  g_return_val_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview), FALSE);
-
-  return GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->is_selected (preview, page_nr);
-}
diff --git a/gtk/gtkprintsettings.c b/gtk/gtkprintsettings.c
deleted file mode 100644 (file)
index 04a02e3..0000000
+++ /dev/null
@@ -1,1866 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkprintsettings.c: Print Settings
- * 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 <stdlib.h>
-
-#include <glib/gprintf.h>
-
-#include "print/gtkprintsettings.h"
-#include "gtkprintutilsprivate.h"
-#include "gtktypebuiltins.h"
-#include "gtkwidget.h"
-
-
-/**
- * GtkPrintSettings:
- *
- * A `GtkPrintSettings` object represents the settings of a print dialog in
- * a system-independent way.
- *
- * The main use for this object is that once you’ve printed you can get a
- * settings object that represents the settings the user chose, and the next
- * time you print you can pass that object in so that the user doesn’t have
- * to re-set all his settings.
- *
- * Its also possible to enumerate the settings so that you can easily save
- * the settings for the next time your app runs, or even store them in a
- * document. The predefined keys try to use shared values as much as possible
- * so that moving such a document between systems still works.
- */
-
-typedef struct _GtkPrintSettingsClass GtkPrintSettingsClass;
-
-#define GTK_IS_PRINT_SETTINGS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_SETTINGS))
-#define GTK_PRINT_SETTINGS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_SETTINGS, GtkPrintSettingsClass))
-#define GTK_PRINT_SETTINGS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_SETTINGS, GtkPrintSettingsClass))
-
-struct _GtkPrintSettings
-{
-  GObject parent_instance;
-
-  GHashTable *hash;
-};
-
-struct _GtkPrintSettingsClass
-{
-  GObjectClass parent_class;
-};
-
-#define KEYFILE_GROUP_NAME "Print Settings"
-
-G_DEFINE_TYPE (GtkPrintSettings, gtk_print_settings, G_TYPE_OBJECT)
-
-static void
-gtk_print_settings_finalize (GObject *object)
-{
-  GtkPrintSettings *settings = GTK_PRINT_SETTINGS (object);
-
-  g_hash_table_destroy (settings->hash);
-
-  G_OBJECT_CLASS (gtk_print_settings_parent_class)->finalize (object);
-}
-
-static void
-gtk_print_settings_init (GtkPrintSettings *settings)
-{
-  settings->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                         g_free, g_free);
-}
-
-static void
-gtk_print_settings_class_init (GtkPrintSettingsClass *class)
-{
-  GObjectClass *gobject_class = (GObjectClass *)class;
-
-  gobject_class->finalize = gtk_print_settings_finalize;
-}
-
-/**
- * gtk_print_settings_new:
- *
- * Creates a new `GtkPrintSettings` object.
- *
- * Returns: a new `GtkPrintSettings` object
- */
-GtkPrintSettings *
-gtk_print_settings_new (void)
-{
-  return g_object_new (GTK_TYPE_PRINT_SETTINGS, NULL);
-}
-
-static void
-copy_hash_entry  (gpointer  key,
-                 gpointer  value,
-                 gpointer  user_data)
-{
-  GtkPrintSettings *settings = user_data;
-
-  g_hash_table_insert (settings->hash, 
-                      g_strdup (key), 
-                      g_strdup (value));
-}
-
-
-
-/**
- * gtk_print_settings_copy:
- * @other: a `GtkPrintSettings`
- *
- * Copies a `GtkPrintSettings` object.
- *
- * Returns: (transfer full): a newly allocated copy of @other
- */
-GtkPrintSettings *
-gtk_print_settings_copy (GtkPrintSettings *other)
-{
-  GtkPrintSettings *settings;
-
-  if (other == NULL)
-    return NULL;
-  
-  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (other), NULL);
-
-  settings = gtk_print_settings_new ();
-
-  g_hash_table_foreach (other->hash,
-                       copy_hash_entry,
-                       settings);
-
-  return settings;
-}
-
-/**
- * gtk_print_settings_get:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Looks up the string value associated with @key.
- *
- * Returns: (nullable): the string value for @key
- */
-const char *
-gtk_print_settings_get (GtkPrintSettings *settings,
-                       const char       *key)
-{
-  return g_hash_table_lookup (settings->hash, key);
-}
-
-/**
- * gtk_print_settings_set:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @value: (nullable): a string value
- *
- * Associates @value with @key.
- */
-void
-gtk_print_settings_set (GtkPrintSettings *settings,
-                       const char       *key,
-                       const char       *value)
-{
-  if (value == NULL)
-    gtk_print_settings_unset (settings, key);
-  else
-    g_hash_table_insert (settings->hash, 
-                        g_strdup (key), 
-                        g_strdup (value));
-}
-
-/**
- * gtk_print_settings_unset:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Removes any value associated with @key.
- *
- * This has the same effect as setting the value to %NULL.
- */
-void
-gtk_print_settings_unset (GtkPrintSettings *settings,
-                         const char       *key)
-{
-  g_hash_table_remove (settings->hash, key);
-}
-
-/**
- * gtk_print_settings_has_key:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Returns %TRUE, if a value is associated with @key.
- *
- * Returns: %TRUE, if @key has a value
- */
-gboolean        
-gtk_print_settings_has_key (GtkPrintSettings *settings,
-                           const char       *key)
-{
-  return gtk_print_settings_get (settings, key) != NULL;
-}
-
-
-/**
- * gtk_print_settings_get_bool:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Returns the boolean represented by the value
- * that is associated with @key.
- *
- * The string “true” represents %TRUE, any other
- * string %FALSE.
- *
- * Returns: %TRUE, if @key maps to a true value.
- */
-gboolean
-gtk_print_settings_get_bool (GtkPrintSettings *settings,
-                            const char       *key)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, key);
-  if (g_strcmp0 (val, "true") == 0)
-    return TRUE;
-  
-  return FALSE;
-}
-
-/**
- * gtk_print_settings_get_bool_with_default:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @default_val: the default value
- *
- * Returns the boolean represented by the value
- * that is associated with @key, or @default_val
- * if the value does not represent a boolean.
- *
- * The string “true” represents %TRUE, the string
- * “false” represents %FALSE.
- *
- * Returns: the boolean value associated with @key
- */
-static gboolean
-gtk_print_settings_get_bool_with_default (GtkPrintSettings *settings,
-                                         const char       *key,
-                                         gboolean          default_val)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, key);
-  if (g_strcmp0 (val, "true") == 0)
-    return TRUE;
-
-  if (g_strcmp0 (val, "false") == 0)
-    return FALSE;
-  
-  return default_val;
-}
-
-/**
- * gtk_print_settings_set_bool:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @value: a boolean
- *
- * Sets @key to a boolean value.
- */
-void
-gtk_print_settings_set_bool (GtkPrintSettings *settings,
-                            const char       *key,
-                            gboolean          value)
-{
-  if (value)
-    gtk_print_settings_set (settings, key, "true");
-  else
-    gtk_print_settings_set (settings, key, "false");
-}
-
-/**
- * gtk_print_settings_get_double_with_default:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @def: the default value
- *
- * Returns the floating point number represented by
- * the value that is associated with @key, or @default_val
- * if the value does not represent a floating point number.
- *
- * Floating point numbers are parsed with g_ascii_strtod().
- *
- * Returns: the floating point number associated with @key
- */
-double
-gtk_print_settings_get_double_with_default (GtkPrintSettings *settings,
-                                           const char       *key,
-                                           double            def)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, key);
-  if (val == NULL)
-    return def;
-
-  return g_ascii_strtod (val, NULL);
-}
-
-/**
- * gtk_print_settings_get_double:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Returns the double value associated with @key, or 0.
- *
- * Returns: the double value of @key
- */
-double
-gtk_print_settings_get_double (GtkPrintSettings *settings,
-                              const char       *key)
-{
-  return gtk_print_settings_get_double_with_default (settings, key, 0.0);
-}
-
-/**
- * gtk_print_settings_set_double:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @value: a double value
- *
- * Sets @key to a double value.
- */
-void
-gtk_print_settings_set_double (GtkPrintSettings *settings,
-                              const char       *key,
-                              double            value)
-{
-  char buf[G_ASCII_DTOSTR_BUF_SIZE];
-  
-  g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, value);
-  gtk_print_settings_set (settings, key, buf);
-}
-
-/**
- * gtk_print_settings_get_length:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @unit: the unit of the return value
- *
- * Returns the value associated with @key, interpreted
- * as a length.
- *
- * The returned value is converted to @units.
- *
- * Returns: the length value of @key, converted to @unit
- */
-double
-gtk_print_settings_get_length (GtkPrintSettings *settings,
-                              const char       *key,
-                              GtkUnit           unit)
-{
-  double length = gtk_print_settings_get_double (settings, key);
-  return _gtk_print_convert_from_mm (length, unit);
-}
-
-/**
- * gtk_print_settings_set_length:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @value: a length
- * @unit: the unit of @length
- *
- * Associates a length in units of @unit with @key.
- */
-void
-gtk_print_settings_set_length (GtkPrintSettings *settings,
-                              const char       *key,
-                              double            value, 
-                              GtkUnit           unit)
-{
-  gtk_print_settings_set_double (settings, key,
-                                _gtk_print_convert_to_mm (value, unit));
-}
-
-/**
- * gtk_print_settings_get_int_with_default:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @def: the default value
- *
- * Returns the value of @key, interpreted as
- * an integer, or the default value.
- *
- * Returns: the integer value of @key
- */
-int
-gtk_print_settings_get_int_with_default (GtkPrintSettings *settings,
-                                        const char       *key,
-                                        int               def)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, key);
-  if (val == NULL)
-    return def;
-
-  return atoi (val);
-}
-
-/**
- * gtk_print_settings_get_int:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- *
- * Returns the integer value of @key, or 0.
- *
- * Returns: the integer value of @key
- */
-int
-gtk_print_settings_get_int (GtkPrintSettings *settings,
-                           const char       *key)
-{
-  return gtk_print_settings_get_int_with_default (settings, key, 0);
-}
-
-/**
- * gtk_print_settings_set_int:
- * @settings: a `GtkPrintSettings`
- * @key: a key
- * @value: an integer
- *
- * Sets @key to an integer value.
- */
-void
-gtk_print_settings_set_int (GtkPrintSettings *settings,
-                           const char       *key,
-                           int               value)
-{
-  char buf[128];
-  g_sprintf (buf, "%d", value);
-  gtk_print_settings_set (settings, key, buf);
-}
-
-/**
- * gtk_print_settings_foreach:
- * @settings: a `GtkPrintSettings`
- * @func: (scope call): the function to call
- * @user_data: (closure): user data for @func
- *
- * Calls @func for each key-value pair of @settings.
- */
-void
-gtk_print_settings_foreach (GtkPrintSettings    *settings,
-                           GtkPrintSettingsFunc func,
-                           gpointer             user_data)
-{
-  g_hash_table_foreach (settings->hash, (GHFunc)func, user_data);
-}
-
-/**
- * gtk_print_settings_get_printer:
- * @settings: a `GtkPrintSettings`
- *
- * Convenience function to obtain the value of
- * %GTK_PRINT_SETTINGS_PRINTER.
- *
- * Returns: (nullable): the printer name
- */
-const char *
-gtk_print_settings_get_printer (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PRINTER);
-}
-
-
-/**
- * gtk_print_settings_set_printer:
- * @settings: a `GtkPrintSettings`
- * @printer: the printer name
- *
- * Convenience function to set %GTK_PRINT_SETTINGS_PRINTER
- * to @printer.
- */
-void
-gtk_print_settings_set_printer (GtkPrintSettings *settings,
-                               const char       *printer)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PRINTER, printer);
-}
-
-/**
- * gtk_print_settings_get_orientation:
- * @settings: a `GtkPrintSettings`
- *
- * Get the value of %GTK_PRINT_SETTINGS_ORIENTATION,
- * converted to a `GtkPageOrientation`.
- *
- * Returns: the orientation
- */
-GtkPageOrientation
-gtk_print_settings_get_orientation (GtkPrintSettings *settings)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_ORIENTATION);
-
-  if (val == NULL || strcmp (val, "portrait") == 0)
-    return GTK_PAGE_ORIENTATION_PORTRAIT;
-
-  if (strcmp (val, "landscape") == 0)
-    return GTK_PAGE_ORIENTATION_LANDSCAPE;
-  
-  if (strcmp (val, "reverse_portrait") == 0)
-    return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
-  
-  if (strcmp (val, "reverse_landscape") == 0)
-    return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
-  
-  return GTK_PAGE_ORIENTATION_PORTRAIT;
-}
-
-/**
- * gtk_print_settings_set_orientation:
- * @settings: a `GtkPrintSettings`
- * @orientation: a page orientation
- *
- * Sets the value of %GTK_PRINT_SETTINGS_ORIENTATION.
- */
-void
-gtk_print_settings_set_orientation (GtkPrintSettings   *settings,
-                                   GtkPageOrientation  orientation)
-{
-  const char *val;
-
-  switch (orientation)
-    {
-    case GTK_PAGE_ORIENTATION_LANDSCAPE:
-      val = "landscape";
-      break;
-    default:
-    case GTK_PAGE_ORIENTATION_PORTRAIT:
-      val = "portrait";
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
-      val = "reverse_landscape";
-      break;
-    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
-      val = "reverse_portrait";
-      break;
-    }
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_ORIENTATION, val);
-}
-
-/**
- * gtk_print_settings_get_paper_size:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PAPER_FORMAT,
- * converted to a `GtkPaperSize`.
- *
- * Returns: (nullable): the paper size
- */
-GtkPaperSize *     
-gtk_print_settings_get_paper_size (GtkPrintSettings *settings)
-{
-  const char *val;
-  const char *name;
-  double w, h;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT);
-  if (val == NULL)
-    return NULL;
-
-  if (g_str_has_prefix (val, "custom-")) 
-    {
-      name = val + strlen ("custom-");
-      w = gtk_print_settings_get_paper_width (settings, GTK_UNIT_MM);
-      h = gtk_print_settings_get_paper_height (settings, GTK_UNIT_MM);
-      return gtk_paper_size_new_custom (name, name, w, h, GTK_UNIT_MM);
-    }
-
-  return gtk_paper_size_new (val);
-}
-
-/**
- * gtk_print_settings_set_paper_size:
- * @settings: a `GtkPrintSettings`
- * @paper_size: a paper size
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PAPER_FORMAT,
- * %GTK_PRINT_SETTINGS_PAPER_WIDTH and
- * %GTK_PRINT_SETTINGS_PAPER_HEIGHT.
- */
-void
-gtk_print_settings_set_paper_size (GtkPrintSettings *settings,
-                                  GtkPaperSize     *paper_size)
-{
-  char *custom_name;
-
-  if (paper_size == NULL) 
-    {
-      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, NULL);
-      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, NULL);
-      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_HEIGHT, NULL);
-    }
-  else if (gtk_paper_size_is_custom (paper_size)) 
-    {
-      custom_name = g_strdup_printf ("custom-%s", 
-                                    gtk_paper_size_get_name (paper_size));
-      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, custom_name);
-      g_free (custom_name);
-      gtk_print_settings_set_paper_width (settings, 
-                                         gtk_paper_size_get_width (paper_size, 
-                                                                   GTK_UNIT_MM),
-                                         GTK_UNIT_MM);
-      gtk_print_settings_set_paper_height (settings, 
-                                          gtk_paper_size_get_height (paper_size, 
-                                                                     GTK_UNIT_MM),
-                                          GTK_UNIT_MM);
-    } 
-  else
-    gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, 
-                           gtk_paper_size_get_name (paper_size));
-}
-
-/**
- * gtk_print_settings_get_paper_width:
- * @settings: a `GtkPrintSettings`
- * @unit: the unit for the return value
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PAPER_WIDTH,
- * converted to @unit.
- *
- * Returns: the paper width, in units of @unit
- */
-double
-gtk_print_settings_get_paper_width (GtkPrintSettings *settings,
-                                   GtkUnit           unit)
-{
-  return gtk_print_settings_get_length (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, unit);
-}
-
-/**
- * gtk_print_settings_set_paper_width:
- * @settings: a `GtkPrintSettings`
- * @width: the paper width
- * @unit: the units of @width
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PAPER_WIDTH.
- */
-void
-gtk_print_settings_set_paper_width (GtkPrintSettings *settings,
-                                   double            width, 
-                                   GtkUnit           unit)
-{
-  gtk_print_settings_set_length (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, width, unit);
-}
-
-/**
- * gtk_print_settings_get_paper_height:
- * @settings: a `GtkPrintSettings`
- * @unit: the unit for the return value
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PAPER_HEIGHT,
- * converted to @unit.
- *
- * Returns: the paper height, in units of @unit
- */
-double
-gtk_print_settings_get_paper_height (GtkPrintSettings *settings,
-                                    GtkUnit           unit)
-{
-  return gtk_print_settings_get_length (settings, 
-                                       GTK_PRINT_SETTINGS_PAPER_HEIGHT,
-                                       unit);
-}
-
-/**
- * gtk_print_settings_set_paper_height:
- * @settings: a `GtkPrintSettings`
- * @height: the paper height
- * @unit: the units of @height
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PAPER_HEIGHT.
- */
-void
-gtk_print_settings_set_paper_height (GtkPrintSettings *settings,
-                                    double            height, 
-                                    GtkUnit           unit)
-{
-  gtk_print_settings_set_length (settings, 
-                                GTK_PRINT_SETTINGS_PAPER_HEIGHT, 
-                                height, unit);
-}
-
-/**
- * gtk_print_settings_get_use_color:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_USE_COLOR.
- *
- * Returns: whether to use color
- */
-gboolean
-gtk_print_settings_get_use_color (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_bool_with_default (settings, 
-                                                  GTK_PRINT_SETTINGS_USE_COLOR,
-                                                  TRUE);
-}
-
-/**
- * gtk_print_settings_set_use_color:
- * @settings: a `GtkPrintSettings`
- * @use_color: whether to use color
- *
- * Sets the value of %GTK_PRINT_SETTINGS_USE_COLOR.
- */
-void
-gtk_print_settings_set_use_color (GtkPrintSettings *settings,
-                                 gboolean          use_color)
-{
-  gtk_print_settings_set_bool (settings,
-                              GTK_PRINT_SETTINGS_USE_COLOR, 
-                              use_color);
-}
-
-/**
- * gtk_print_settings_get_collate:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_COLLATE.
- *
- * Returns: whether to collate the printed pages
- */
-gboolean
-gtk_print_settings_get_collate (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_bool_with_default (settings,
-                                                   GTK_PRINT_SETTINGS_COLLATE,
-                                                   TRUE);
-}
-
-/**
- * gtk_print_settings_set_collate:
- * @settings: a `GtkPrintSettings`
- * @collate: whether to collate the output
- *
- * Sets the value of %GTK_PRINT_SETTINGS_COLLATE.
- */
-void
-gtk_print_settings_set_collate (GtkPrintSettings *settings,
-                               gboolean          collate)
-{
-  gtk_print_settings_set_bool (settings,
-                              GTK_PRINT_SETTINGS_COLLATE, 
-                              collate);
-}
-
-/**
- * gtk_print_settings_get_reverse:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_REVERSE.
- *
- * Returns:  whether to reverse the order of the printed pages
- */
-gboolean
-gtk_print_settings_get_reverse (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_bool (settings, 
-                                     GTK_PRINT_SETTINGS_REVERSE);
-}
-
-/**
- * gtk_print_settings_set_reverse:
- * @settings: a `GtkPrintSettings`
- * @reverse: whether to reverse the output
- *
- * Sets the value of %GTK_PRINT_SETTINGS_REVERSE.
- */
-void
-gtk_print_settings_set_reverse (GtkPrintSettings *settings,
-                                 gboolean        reverse)
-{
-  gtk_print_settings_set_bool (settings,
-                              GTK_PRINT_SETTINGS_REVERSE, 
-                              reverse);
-}
-
-/**
- * gtk_print_settings_get_duplex:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_DUPLEX.
- *
- * Returns: whether to print the output in duplex.
- */
-GtkPrintDuplex
-gtk_print_settings_get_duplex (GtkPrintSettings *settings)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DUPLEX);
-
-  if (val == NULL || (strcmp (val, "simplex") == 0))
-    return GTK_PRINT_DUPLEX_SIMPLEX;
-
-  if (strcmp (val, "horizontal") == 0)
-    return GTK_PRINT_DUPLEX_HORIZONTAL;
-  
-  if (strcmp (val, "vertical") == 0)
-    return GTK_PRINT_DUPLEX_VERTICAL;
-  
-  return GTK_PRINT_DUPLEX_SIMPLEX;
-}
-
-/**
- * gtk_print_settings_set_duplex:
- * @settings: a `GtkPrintSettings`
- * @duplex: a `GtkPrintDuplex` value
- *
- * Sets the value of %GTK_PRINT_SETTINGS_DUPLEX.
- */
-void
-gtk_print_settings_set_duplex (GtkPrintSettings *settings,
-                              GtkPrintDuplex    duplex)
-{
-  const char *str;
-
-  switch (duplex)
-    {
-    default:
-    case GTK_PRINT_DUPLEX_SIMPLEX:
-      str = "simplex";
-      break;
-    case GTK_PRINT_DUPLEX_HORIZONTAL:
-      str = "horizontal";
-      break;
-    case GTK_PRINT_DUPLEX_VERTICAL:
-      str = "vertical";
-      break;
-    }
-  
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DUPLEX, str);
-}
-
-/**
- * gtk_print_settings_get_quality:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_QUALITY.
- *
- * Returns: the print quality
- */
-GtkPrintQuality
-gtk_print_settings_get_quality (GtkPrintSettings *settings)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_QUALITY);
-
-  if (val == NULL || (strcmp (val, "normal") == 0))
-    return GTK_PRINT_QUALITY_NORMAL;
-
-  if (strcmp (val, "high") == 0)
-    return GTK_PRINT_QUALITY_HIGH;
-  
-  if (strcmp (val, "low") == 0)
-    return GTK_PRINT_QUALITY_LOW;
-  
-  if (strcmp (val, "draft") == 0)
-    return GTK_PRINT_QUALITY_DRAFT;
-  
-  return GTK_PRINT_QUALITY_NORMAL;
-}
-
-/**
- * gtk_print_settings_set_quality:
- * @settings: a `GtkPrintSettings`
- * @quality: a `GtkPrintQuality` value
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_QUALITY.
- */
-void
-gtk_print_settings_set_quality (GtkPrintSettings *settings,
-                               GtkPrintQuality   quality)
-{
-  const char *str;
-
-  switch (quality)
-    {
-    default:
-    case GTK_PRINT_QUALITY_NORMAL:
-      str = "normal";
-      break;
-    case GTK_PRINT_QUALITY_HIGH:
-      str = "high";
-      break;
-    case GTK_PRINT_QUALITY_LOW:
-      str = "low";
-      break;
-    case GTK_PRINT_QUALITY_DRAFT:
-      str = "draft";
-      break;
-    }
-  
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_QUALITY, str);
-}
-
-/**
- * gtk_print_settings_get_page_set:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PAGE_SET.
- *
- * Returns: the set of pages to print
- */
-GtkPageSet
-gtk_print_settings_get_page_set (GtkPrintSettings *settings)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAGE_SET);
-
-  if (val == NULL || (strcmp (val, "all") == 0))
-    return GTK_PAGE_SET_ALL;
-
-  if (strcmp (val, "even") == 0)
-    return GTK_PAGE_SET_EVEN;
-  
-  if (strcmp (val, "odd") == 0)
-    return GTK_PAGE_SET_ODD;
-  
-  return GTK_PAGE_SET_ALL;
-}
-
-/**
- * gtk_print_settings_set_page_set:
- * @settings: a `GtkPrintSettings`
- * @page_set: a `GtkPageSet` value
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PAGE_SET.
- */
-void
-gtk_print_settings_set_page_set (GtkPrintSettings *settings,
-                                GtkPageSet        page_set)
-{
-  const char *str;
-
-  switch (page_set)
-    {
-    default:
-    case GTK_PAGE_SET_ALL:
-      str = "all";
-      break;
-    case GTK_PAGE_SET_EVEN:
-      str = "even";
-      break;
-    case GTK_PAGE_SET_ODD:
-      str = "odd";
-      break;
-    }
-  
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAGE_SET, str);
-}
-
-/**
- * gtk_print_settings_get_number_up_layout:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT.
- *
- * Returns: layout of page in number-up mode
- */
-GtkNumberUpLayout
-gtk_print_settings_get_number_up_layout (GtkPrintSettings *settings)
-{
-  GtkNumberUpLayout layout;
-  GtkTextDirection  text_direction;
-  GEnumClass       *enum_class;
-  GEnumValue       *enum_value;
-  const char       *val;
-
-  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT);
-  text_direction = gtk_widget_get_default_direction ();
-
-  if (text_direction == 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;
-
-  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;
-}
-
-/**
- * gtk_print_settings_set_number_up_layout:
- * @settings: a `GtkPrintSettings`
- * @number_up_layout: a `GtkNumberUpLayout` value
- *
- * Sets the value of %GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT.
- */
-void
-gtk_print_settings_set_number_up_layout (GtkPrintSettings  *settings,
-                                        GtkNumberUpLayout  number_up_layout)
-{
-  GEnumClass *enum_class;
-  GEnumValue *enum_value;
-
-  g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
-
-  enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
-  enum_value = g_enum_get_value (enum_class, number_up_layout);
-  g_return_if_fail (enum_value != NULL);
-
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, enum_value->value_nick);
-  g_type_class_unref (enum_class);
-}
-
-/**
- * gtk_print_settings_get_n_copies:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_N_COPIES.
- * 
- * Returns: the number of copies to print
- */
-int
-gtk_print_settings_get_n_copies (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_N_COPIES, 1);
-}
-
-/**
- * gtk_print_settings_set_n_copies:
- * @settings: a `GtkPrintSettings`
- * @num_copies: the number of copies
- *
- * Sets the value of %GTK_PRINT_SETTINGS_N_COPIES.
- */
-void
-gtk_print_settings_set_n_copies (GtkPrintSettings *settings,
-                                int               num_copies)
-{
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_N_COPIES,
-                             num_copies);
-}
-
-/**
- * gtk_print_settings_get_number_up:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_NUMBER_UP.
- *
- * Returns: the number of pages per sheet
- */
-int
-gtk_print_settings_get_number_up (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_NUMBER_UP, 1);
-}
-
-/**
- * gtk_print_settings_set_number_up:
- * @settings: a `GtkPrintSettings`
- * @number_up: the number of pages per sheet
- *
- * Sets the value of %GTK_PRINT_SETTINGS_NUMBER_UP.
- */
-void
-gtk_print_settings_set_number_up (GtkPrintSettings *settings,
-                                 int               number_up)
-{
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_NUMBER_UP,
-                               number_up);
-}
-
-/**
- * gtk_print_settings_get_resolution:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION.
- *
- * Returns: the resolution in dpi
- */
-int
-gtk_print_settings_get_resolution (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION, 300);
-}
-
-/**
- * gtk_print_settings_set_resolution:
- * @settings: a `GtkPrintSettings`
- * @resolution: the resolution in dpi
- *
- * Sets the values of %GTK_PRINT_SETTINGS_RESOLUTION,
- * %GTK_PRINT_SETTINGS_RESOLUTION_X and
- * %GTK_PRINT_SETTINGS_RESOLUTION_Y.
- */
-void
-gtk_print_settings_set_resolution (GtkPrintSettings *settings,
-                                  int               resolution)
-{
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION,
-                             resolution);
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_X,
-                             resolution);
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y,
-                             resolution);
-}
-
-/**
- * gtk_print_settings_get_resolution_x:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION_X.
- *
- * Returns: the horizontal resolution in dpi
- */
-int
-gtk_print_settings_get_resolution_x (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_X, 300);
-}
-
-/**
- * gtk_print_settings_get_resolution_y:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION_Y.
- *
- * Returns: the vertical resolution in dpi
- */
-int
-gtk_print_settings_get_resolution_y (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y, 300);
-}
-
-/**
- * gtk_print_settings_set_resolution_xy:
- * @settings: a `GtkPrintSettings`
- * @resolution_x: the horizontal resolution in dpi
- * @resolution_y: the vertical resolution in dpi
- *
- * Sets the values of %GTK_PRINT_SETTINGS_RESOLUTION,
- * %GTK_PRINT_SETTINGS_RESOLUTION_X and
- * %GTK_PRINT_SETTINGS_RESOLUTION_Y.
- */
-void
-gtk_print_settings_set_resolution_xy (GtkPrintSettings *settings,
-                                     int               resolution_x,
-                                     int               resolution_y)
-{
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_X,
-                             resolution_x);
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y,
-                             resolution_y);
-  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION,
-                             resolution_x);
-}
-
-/**
- * gtk_print_settings_get_printer_lpi:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PRINTER_LPI.
- *
- * Returns: the resolution in lpi (lines per inch)
- */
-double
-gtk_print_settings_get_printer_lpi (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_double_with_default (settings, GTK_PRINT_SETTINGS_PRINTER_LPI, 150.0);
-}
-
-/**
- * gtk_print_settings_set_printer_lpi:
- * @settings: a `GtkPrintSettings`
- * @lpi: the resolution in lpi (lines per inch)
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PRINTER_LPI.
- */
-void
-gtk_print_settings_set_printer_lpi (GtkPrintSettings *settings,
-                                   double            lpi)
-{
-  gtk_print_settings_set_double (settings, GTK_PRINT_SETTINGS_PRINTER_LPI,
-                                lpi);
-}
-
-/**
- * gtk_print_settings_get_scale:
- * @settings: a `GtkPrintSettings`
- *
- * Gets the value of %GTK_PRINT_SETTINGS_SCALE.
- *
- * Returns: the scale in percent
- */
-double
-gtk_print_settings_get_scale (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get_double_with_default (settings,
-                                                    GTK_PRINT_SETTINGS_SCALE,
-                                                    100.0);
-}
-
-/**
- * gtk_print_settings_set_scale:
- * @settings: a `GtkPrintSettings`
- * @scale: the scale in percent
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_SCALE.
- */
-void
-gtk_print_settings_set_scale (GtkPrintSettings *settings,
-                             double            scale)
-{
-  gtk_print_settings_set_double (settings, GTK_PRINT_SETTINGS_SCALE,
-                                scale);
-}
-
-/**
- * gtk_print_settings_get_print_pages:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_PRINT_PAGES.
- * 
- * Returns: which pages to print
- */
-GtkPrintPages
-gtk_print_settings_get_print_pages (GtkPrintSettings *settings)
-{
-  const char *val;
-
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PRINT_PAGES);
-
-  if (val == NULL || (strcmp (val, "all") == 0))
-    return GTK_PRINT_PAGES_ALL;
-
-  if (strcmp (val, "selection") == 0)
-    return GTK_PRINT_PAGES_SELECTION;
-
-  if (strcmp (val, "current") == 0)
-    return GTK_PRINT_PAGES_CURRENT;
-  
-  if (strcmp (val, "ranges") == 0)
-    return GTK_PRINT_PAGES_RANGES;
-  
-  return GTK_PRINT_PAGES_ALL;
-}
-
-/**
- * gtk_print_settings_set_print_pages:
- * @settings: a `GtkPrintSettings`
- * @pages: a `GtkPrintPages` value
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_PRINT_PAGES.
- */
-void
-gtk_print_settings_set_print_pages (GtkPrintSettings *settings,
-                                   GtkPrintPages     pages)
-{
-  const char *str;
-
-  switch (pages)
-    {
-    default:
-    case GTK_PRINT_PAGES_ALL:
-      str = "all";
-      break;
-    case GTK_PRINT_PAGES_CURRENT:
-      str = "current";
-      break;
-    case GTK_PRINT_PAGES_SELECTION:
-      str = "selection";
-      break;
-    case GTK_PRINT_PAGES_RANGES:
-      str = "ranges";
-      break;
-    }
-  
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PRINT_PAGES, str);
-}
-
-/**
- * gtk_print_settings_get_page_ranges:
- * @settings: a `GtkPrintSettings`
- * @num_ranges: (out): return location for the length of the returned array
- *
- * Gets the value of %GTK_PRINT_SETTINGS_PAGE_RANGES.
- *
- * Returns: (array length=num_ranges) (transfer full): an array
- *   of `GtkPageRange`s. Use g_free() to free the array when
- *   it is no longer needed.
- */
-GtkPageRange *
-gtk_print_settings_get_page_ranges (GtkPrintSettings *settings,
-                                   int              *num_ranges)
-{
-  const char *val;
-  char **range_strs;
-  GtkPageRange *ranges;
-  int i, n;
-  
-  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAGE_RANGES);
-
-  if (val == NULL)
-    {
-      *num_ranges = 0;
-      return NULL;
-    }
-  
-  range_strs = g_strsplit (val, ",", 0);
-
-  for (i = 0; range_strs[i] != NULL; i++)
-    ;
-
-  n = i;
-
-  ranges = g_new0 (GtkPageRange, n);
-
-  for (i = 0; i < n; i++)
-    {
-      int start, end;
-      char *str;
-
-      start = (int)strtol (range_strs[i], &str, 10);
-      end = start;
-
-      if (*str == '-')
-       {
-         str++;
-         end = (int)strtol (str, NULL, 10);
-       }
-
-      ranges[i].start = start;
-      ranges[i].end = end;
-    }
-
-  g_strfreev (range_strs);
-
-  *num_ranges = n;
-  return ranges;
-}
-
-/**
- * gtk_print_settings_set_page_ranges:
- * @settings: a `GtkPrintSettings`
- * @page_ranges: (array length=num_ranges): an array of `GtkPageRange`s
- * @num_ranges: the length of @page_ranges
- *
- * Sets the value of %GTK_PRINT_SETTINGS_PAGE_RANGES.
- */
-void
-gtk_print_settings_set_page_ranges  (GtkPrintSettings *settings,
-                                    GtkPageRange     *page_ranges,
-                                    int               num_ranges)
-{
-  GString *s;
-  int i;
-  
-  s = g_string_new ("");
-
-  for (i = 0; i < num_ranges; i++)
-    {
-      if (page_ranges[i].start == page_ranges[i].end)
-       g_string_append_printf (s, "%d", page_ranges[i].start);
-      else
-       g_string_append_printf (s, "%d-%d",
-                               page_ranges[i].start,
-                               page_ranges[i].end);
-      if (i < num_ranges - 1)
-       g_string_append (s, ",");
-    }
-
-  
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAGE_RANGES, 
-                         s->str);
-
-  g_string_free (s, TRUE);
-}
-
-/**
- * gtk_print_settings_get_default_source:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_DEFAULT_SOURCE.
- * 
- * Returns: (nullable): the default source
- */
-const char *
-gtk_print_settings_get_default_source (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE);
-}
-
-/**
- * gtk_print_settings_set_default_source:
- * @settings: a `GtkPrintSettings`
- * @default_source: the default source
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_DEFAULT_SOURCE.
- */
-void
-gtk_print_settings_set_default_source (GtkPrintSettings *settings,
-                                      const char       *default_source)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE, default_source);
-}
-     
-/**
- * gtk_print_settings_get_media_type:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_MEDIA_TYPE.
- *
- * The set of media types is defined in PWG 5101.1-2002 PWG.
- * 
- * Returns: (nullable): the media type
- */
-const char *
-gtk_print_settings_get_media_type (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE);
-}
-
-/**
- * gtk_print_settings_set_media_type:
- * @settings: a `GtkPrintSettings`
- * @media_type: the media type
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_MEDIA_TYPE.
- * 
- * The set of media types is defined in PWG 5101.1-2002 PWG.
- */
-void
-gtk_print_settings_set_media_type (GtkPrintSettings *settings,
-                                  const char       *media_type)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE, media_type);
-}
-
-/**
- * gtk_print_settings_get_dither:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_DITHER.
- * 
- * Returns: (nullable): the dithering that is used
- */
-const char *
-gtk_print_settings_get_dither (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DITHER);
-}
-
-/**
- * gtk_print_settings_set_dither:
- * @settings: a `GtkPrintSettings`
- * @dither: the dithering that is used
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_DITHER.
- */
-void
-gtk_print_settings_set_dither (GtkPrintSettings *settings,
-                              const char       *dither)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DITHER, dither);
-}
-     
-/**
- * gtk_print_settings_get_finishings:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_FINISHINGS.
- * 
- * Returns: (nullable): the finishings
- */
-const char *
-gtk_print_settings_get_finishings (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_FINISHINGS);
-}
-
-/**
- * gtk_print_settings_set_finishings:
- * @settings: a `GtkPrintSettings`
- * @finishings: the finishings
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_FINISHINGS.
- */
-void
-gtk_print_settings_set_finishings (GtkPrintSettings *settings,
-                                  const char       *finishings)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_FINISHINGS, finishings);
-}
-     
-/**
- * gtk_print_settings_get_output_bin:
- * @settings: a `GtkPrintSettings`
- * 
- * Gets the value of %GTK_PRINT_SETTINGS_OUTPUT_BIN.
- * 
- * Returns: (nullable): the output bin
- */
-const char *
-gtk_print_settings_get_output_bin (GtkPrintSettings *settings)
-{
-  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_BIN);
-}
-
-/**
- * gtk_print_settings_set_output_bin:
- * @settings: a `GtkPrintSettings`
- * @output_bin: the output bin
- * 
- * Sets the value of %GTK_PRINT_SETTINGS_OUTPUT_BIN.
- */
-void
-gtk_print_settings_set_output_bin (GtkPrintSettings *settings,
-                                  const char       *output_bin)
-{
-  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BIN, output_bin);
-}
-
-/**
- * gtk_print_settings_load_file:
- * @settings: a `GtkPrintSettings`
- * @file_name: (type filename): the filename to read the settings from
- * @error: (nullable): return location for errors
- *
- * Reads the print settings from @file_name.
- *
- * If the file could not be loaded then error is set to either
- * a `GFileError` or `GKeyFileError`.
- *
- * See [method@Gtk.PrintSettings.to_file].
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_print_settings_load_file (GtkPrintSettings *settings,
-                              const char       *file_name,
-                              GError          **error)
-{
-  gboolean retval = FALSE;
-  GKeyFile *key_file;
-
-  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
-  g_return_val_if_fail (file_name != NULL, FALSE);
-
-  key_file = g_key_file_new ();
-
-  if (g_key_file_load_from_file (key_file, file_name, 0, error) &&
-      gtk_print_settings_load_key_file (settings, key_file, NULL, error))
-    retval = TRUE;
-
-  g_key_file_free (key_file);
-
-  return retval;
-}
-
-/**
- * gtk_print_settings_new_from_file:
- * @file_name: (type filename): the filename to read the settings from
- * @error: (nullable): return location for errors
- *
- * Reads the print settings from @file_name.
- *
- * Returns a new `GtkPrintSettings` object with the restored settings,
- * or %NULL if an error occurred. If the file could not be loaded then
- * error is set to either a `GFileError` or `GKeyFileError`.
- *
- * See [method@Gtk.PrintSettings.to_file].
- *
- * Returns: the restored `GtkPrintSettings`
- */
-GtkPrintSettings *
-gtk_print_settings_new_from_file (const char   *file_name,
-                                 GError      **error)
-{
-  GtkPrintSettings *settings = gtk_print_settings_new ();
-
-  if (!gtk_print_settings_load_file (settings, file_name, error))
-    {
-      g_object_unref (settings);
-      settings = NULL;
-    }
-
-  return settings;
-}
-
-/**
- * gtk_print_settings_load_key_file:
- * @settings: a `GtkPrintSettings`
- * @key_file: the `GKeyFile` to retrieve the settings from
- * @group_name: (nullable): the name of the group to use, or %NULL
- *   to use the default “Print Settings”
- * @error: (nullable): return location for errors
- *
- * Reads the print settings from the group @group_name in @key_file.
- *
- * If the file could not be loaded then error is set to either a
- * `GFileError` or `GKeyFileError`.
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_print_settings_load_key_file (GtkPrintSettings *settings,
-                                 GKeyFile         *key_file,
-                                 const char       *group_name,
-                                 GError          **error)
-{
-  char **keys;
-  gsize n_keys, i;
-  GError *err = NULL;
-
-  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
-  g_return_val_if_fail (key_file != NULL, FALSE);
-
-  if (!group_name)
-    group_name = KEYFILE_GROUP_NAME;
-
-  keys = g_key_file_get_keys (key_file,
-                             group_name,
-                             &n_keys,
-                             &err);
-  if (err != NULL)
-    {
-      g_propagate_error (error, err);
-      return FALSE;
-    }
-   
-  for (i = 0 ; i < n_keys; ++i)
-    {
-      char *value;
-
-      value = g_key_file_get_string (key_file,
-                                    group_name,
-                                    keys[i],
-                                    NULL);
-      if (!value)
-        continue;
-
-      gtk_print_settings_set (settings, keys[i], value);
-      g_free (value);
-    }
-
-  g_strfreev (keys);
-
-  return TRUE;
-}
-
-/**
- * gtk_print_settings_new_from_key_file:
- * @key_file: the `GKeyFile` to retrieve the settings from
- * @group_name: (nullable): the name of the group to use, or %NULL to use
- *   the default “Print Settings”
- * @error: (nullable): return location for errors
- *
- * Reads the print settings from the group @group_name in @key_file.
- *
- * Returns a new `GtkPrintSettings` object with the restored settings,
- * or %NULL if an error occurred. If the file could not be loaded then
- * error is set to either `GFileError` or `GKeyFileError`.
- *
- * Returns: the restored `GtkPrintSettings`
- */
-GtkPrintSettings *
-gtk_print_settings_new_from_key_file (GKeyFile     *key_file,
-                                     const char   *group_name,
-                                     GError      **error)
-{
-  GtkPrintSettings *settings = gtk_print_settings_new ();
-
-  if (!gtk_print_settings_load_key_file (settings, key_file,
-                                         group_name, error))
-    {
-      g_object_unref (settings);
-      settings = NULL;
-    }
-
-  return settings;
-}
-
-/**
- * gtk_print_settings_to_file:
- * @settings: a `GtkPrintSettings`
- * @file_name: (type filename): the file to save to
- * @error: (nullable): return location for errors
- *
- * This function saves the print settings from @settings to @file_name.
- *
- * If the file could not be written then error is set to either a
- * `GFileError` or `GKeyFileError`.
- *
- * Returns: %TRUE on success
- */
-gboolean
-gtk_print_settings_to_file (GtkPrintSettings  *settings,
-                           const char        *file_name,
-                           GError           **error)
-{
-  GKeyFile *key_file;
-  gboolean retval = FALSE;
-  char *data = NULL;
-  gsize len;
-  GError *err = NULL;
-
-  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
-  g_return_val_if_fail (file_name != NULL, FALSE);
-
-  key_file = g_key_file_new ();
-  gtk_print_settings_to_key_file (settings, key_file, NULL);
-
-  data = g_key_file_to_data (key_file, &len, &err);
-  if (!data)
-    goto out;
-
-  retval = g_file_set_contents (file_name, data, len, &err);
-
-out:
-  if (err != NULL)
-    g_propagate_error (error, err);
-
-  g_key_file_free (key_file);
-  g_free (data);
-
-  return retval;
-}
-
-typedef struct {
-  GKeyFile *key_file;
-  const char *group_name;
-} SettingsData;
-
-static void
-add_value_to_key_file (const char   *key,
-                      const char   *value,
-                      SettingsData *data)
-{
-  g_key_file_set_string (data->key_file, data->group_name, key, value);
-}
-
-/**
- * gtk_print_settings_to_key_file:
- * @settings: a `GtkPrintSettings`
- * @key_file: the `GKeyFile` to save the print settings to
- * @group_name: (nullable): the group to add the settings to in @key_file, or
- *   %NULL to use the default “Print Settings”
- *
- * This function adds the print settings from @settings to @key_file.
- */
-void
-gtk_print_settings_to_key_file (GtkPrintSettings  *settings,
-                               GKeyFile          *key_file,
-                               const char        *group_name)
-{
-  SettingsData data;
-
-  g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
-  g_return_if_fail (key_file != NULL);
-
-  if (!group_name)
-    group_name = KEYFILE_GROUP_NAME;
-
-  data.key_file = key_file;
-  data.group_name = group_name;
-
-  gtk_print_settings_foreach (settings,
-                             (GtkPrintSettingsFunc) add_value_to_key_file,
-                             &data);
-}
-
-static void
-add_to_variant (const char *key,
-                const char *value,
-                gpointer     data)
-{
-  GVariantBuilder *builder = data;
-  g_variant_builder_add (builder, "{sv}", key, g_variant_new_string (value));
-}
-
-/**
- * gtk_print_settings_to_gvariant:
- * @settings: a `GtkPrintSettings`
- *
- * Serialize print settings to an a{sv} variant.
- *
- * Returns: (transfer none): a new, floating, `GVariant`
- */
-GVariant *
-gtk_print_settings_to_gvariant (GtkPrintSettings *settings)
-{
-  GVariantBuilder builder;
-
-  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
-  gtk_print_settings_foreach (settings, add_to_variant, &builder);
-
-  return g_variant_builder_end (&builder);
-}
-
-/**
- * gtk_print_settings_new_from_gvariant:
- * @variant: an a{sv} `GVariant`
- *
- * Deserialize print settings from an a{sv} variant.
- *
- * The variant must be in the format produced by
- * [method@Gtk.PrintSettings.to_gvariant].
- *
- * Returns: (transfer full): a new `GtkPrintSettings` object
- */
-GtkPrintSettings *
-gtk_print_settings_new_from_gvariant (GVariant *variant)
-{
-  GtkPrintSettings *settings;
-  int i;
-
-  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
-
-  settings = gtk_print_settings_new ();
-
-  for (i = 0; i < g_variant_n_children (variant); i++)
-    {
-      const char *key;
-      GVariant *v;
-
-      g_variant_get_child (variant, i, "{&sv}", &key, &v);
-      if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
-        gtk_print_settings_set (settings, key, g_variant_get_string (v, NULL));
-      g_variant_unref (v);
-    }
-
-  return settings;
-}
diff --git a/gtk/gtkprintutils.c b/gtk/gtkprintutils.c
deleted file mode 100644 (file)
index 105ad08..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* GTK - The GIMP Toolkit
- * gtkpapersize.c: Paper Size
- * 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 "gtkprintutilsprivate.h"
-
-double
-_gtk_print_convert_to_mm (double len, 
-                         GtkUnit unit)
-{
-  switch (unit)
-    {
-    case GTK_UNIT_MM:
-      return len;
-    case GTK_UNIT_INCH:
-      return len * MM_PER_INCH;
-    case GTK_UNIT_NONE:
-    default:
-      g_warning ("Unsupported unit");
-      G_GNUC_FALLTHROUGH;
-    case GTK_UNIT_POINTS:
-      return len * (MM_PER_INCH / POINTS_PER_INCH);
-      break;
-    }
-}
-
-double
-_gtk_print_convert_from_mm (double len, 
-                           GtkUnit unit)
-{
-  switch (unit)
-    {
-    case GTK_UNIT_MM:
-      return len;
-    case GTK_UNIT_INCH:
-      return len / MM_PER_INCH;
-    case GTK_UNIT_NONE:
-    default:
-      g_warning ("Unsupported unit");
-      G_GNUC_FALLTHROUGH;
-    case GTK_UNIT_POINTS:
-      return len / (MM_PER_INCH / POINTS_PER_INCH);
-      break;
-    }
-}
index 824d3c01290ee9900bda278be73409fa6a8c6958..479a7b6269d6e6f244bae161960e3625abe3a1ee 100644 (file)
@@ -1,6 +1,7 @@
 subdir('a11y')
 subdir('deprecated')
 subdir('inspector')
+subdir('print')
 
 gtk_cargs = [
   '-DGTK_COMPILATION',
@@ -128,7 +129,6 @@ gtk_private_sources = files([
   'gtkplacesviewrow.c',
   'gtkpointerfocus.c',
   'gtkpopovercontent.c',
-  'gtkprintutils.c',
   'gtkprivate.c',
   'gtkprogresstracker.c',
   'gtkrbtree.c',
@@ -303,19 +303,13 @@ gtk_public_sources = files([
   'gtkoverlay.c',
   'gtkoverlaylayout.c',
   'gtkpadcontroller.c',
-  'gtkpagesetup.c',
   'gtkpaned.c',
-  'gtkpapersize.c',
   'gtkpasswordentry.c',
   'gtkpasswordentrybuffer.c',
   'gtkpicture.c',
   'gtkpopover.c',
   'gtkpopovermenu.c',
   'gtkpopovermenubar.c',
-  'gtkprintcontext.c',
-  'gtkprintoperation.c',
-  'gtkprintoperationpreview.c',
-  'gtkprintsettings.c',
   'gtkprogressbar.c',
   'gtkpropertylookuplistmodel.c',
   'gtkrange.c',
@@ -407,6 +401,8 @@ gtk_public_sources = files([
   'gtkwindowhandle.c',
 ])
 
+gtk_public_sources += gtk_print_sources
+
 gtk_private_type_headers = files([
   'gtkcsstypesprivate.h',
   'gtktexthandleprivate.h',
@@ -626,8 +622,6 @@ gtk_public_headers = files([
   'gtk.h',
 ])
 
-subdir('print')
-
 install_headers(gtk_public_headers, subdir: 'gtk-4.0/gtk/')
 install_headers(gtk_deprecated_headers, subdir: 'gtk-4.0/gtk/deprecated')
 install_headers(gtk_print_headers, subdir: 'gtk-4.0/gtk/print')
diff --git a/gtk/print/gtkpagesetup.c b/gtk/print/gtkpagesetup.c
new file mode 100644 (file)
index 0000000..588e43d
--- /dev/null
@@ -0,0 +1,876 @@
+/* GTK - The GIMP Toolkit
+ * gtkpagesetup.c: Page Setup
+ * 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 "gtkpagesetup.h"
+#include "gtkprintutilsprivate.h"
+#include "gtkprintoperation.h" /* for GtkPrintError */
+#include <glib/gi18n-lib.h>
+#include "gtktypebuiltins.h"
+
+/**
+ * GtkPageSetup:
+ *
+ * A `GtkPageSetup` object stores the page size, orientation and margins.
+ *
+ * The idea is that you can get one of these from the page setup dialog
+ * and then pass it to the `GtkPrintOperation` when printing.
+ * The benefit of splitting this out of the `GtkPrintSettings` is that
+ * these affect the actual layout of the page, and thus need to be set
+ * long before user prints.
+ *
+ * ## Margins
+ *
+ * The margins specified in this object are the “print margins”, i.e. the
+ * parts of the page that the printer cannot print on. These are different
+ * from the layout margins that a word processor uses; they are typically
+ * used to determine the minimal size for the layout margins.
+ *
+ * To obtain a `GtkPageSetup` use [ctor@Gtk.PageSetup.new] to get the defaults,
+ * or use [func@Gtk.print_run_page_setup_dialog] to show the page setup dialog
+ * and receive the resulting page setup.
+ *
+ * ## A page setup dialog
+ *
+ * ```c
+ * static GtkPrintSettings *settings = NULL;
+ * static GtkPageSetup *page_setup = NULL;
+ *
+ * static void
+ * do_page_setup (void)
+ * {
+ *   GtkPageSetup *new_page_setup;
+ *
+ *   if (settings == NULL)
+ *     settings = gtk_print_settings_new ();
+ *
+ *   new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (main_window),
+ *                                                     page_setup, settings);
+ *
+ *   if (page_setup)
+ *     g_object_unref (page_setup);
+ *
+ *   page_setup = new_page_setup;
+ * }
+ * ```
+ */
+
+#define KEYFILE_GROUP_NAME "Page Setup"
+
+typedef struct _GtkPageSetupClass GtkPageSetupClass;
+
+#define GTK_IS_PAGE_SETUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PAGE_SETUP))
+#define GTK_PAGE_SETUP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PAGE_SETUP, GtkPageSetupClass))
+#define GTK_PAGE_SETUP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PAGE_SETUP, GtkPageSetupClass))
+
+struct _GtkPageSetup
+{
+  GObject parent_instance;
+
+  GtkPageOrientation orientation;
+  GtkPaperSize *paper_size;
+  /* These are stored in mm */
+  double top_margin, bottom_margin, left_margin, right_margin;
+};
+
+struct _GtkPageSetupClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkPageSetup, gtk_page_setup, G_TYPE_OBJECT)
+
+static void
+gtk_page_setup_finalize (GObject *object)
+{
+  GtkPageSetup *setup = GTK_PAGE_SETUP (object);
+  
+  gtk_paper_size_free (setup->paper_size);
+  
+  G_OBJECT_CLASS (gtk_page_setup_parent_class)->finalize (object);
+}
+
+static void
+gtk_page_setup_init (GtkPageSetup *setup)
+{
+  setup->paper_size = gtk_paper_size_new (NULL);
+  setup->orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
+  setup->top_margin = gtk_paper_size_get_default_top_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->bottom_margin = gtk_paper_size_get_default_bottom_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->left_margin = gtk_paper_size_get_default_left_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->right_margin = gtk_paper_size_get_default_right_margin (setup->paper_size, GTK_UNIT_MM);
+}
+
+static void
+gtk_page_setup_class_init (GtkPageSetupClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->finalize = gtk_page_setup_finalize;
+}
+
+/**
+ * gtk_page_setup_new:
+ *
+ * Creates a new `GtkPageSetup`.
+ *
+ * Returns: a new `GtkPageSetup`.
+ */
+GtkPageSetup *
+gtk_page_setup_new (void)
+{
+  return g_object_new (GTK_TYPE_PAGE_SETUP, NULL);
+}
+
+/**
+ * gtk_page_setup_copy:
+ * @other: the `GtkPageSetup` to copy
+ *
+ * Copies a `GtkPageSetup`.
+ *
+ * Returns: (transfer full): a copy of @other
+ */
+GtkPageSetup *
+gtk_page_setup_copy (GtkPageSetup *other)
+{
+  GtkPageSetup *copy;
+
+  copy = gtk_page_setup_new ();
+  copy->orientation = other->orientation;
+  gtk_paper_size_free (copy->paper_size);
+  copy->paper_size = gtk_paper_size_copy (other->paper_size);
+  copy->top_margin = other->top_margin;
+  copy->bottom_margin = other->bottom_margin;
+  copy->left_margin = other->left_margin;
+  copy->right_margin = other->right_margin;
+
+  return copy;
+}
+
+/**
+ * gtk_page_setup_get_orientation:
+ * @setup: a `GtkPageSetup`
+ *
+ * Gets the page orientation of the `GtkPageSetup`.
+ *
+ * Returns: the page orientation
+ */
+GtkPageOrientation
+gtk_page_setup_get_orientation (GtkPageSetup *setup)
+{
+  return setup->orientation;
+}
+
+/**
+ * gtk_page_setup_set_orientation:
+ * @setup: a `GtkPageSetup`
+ * @orientation: a `GtkPageOrientation` value
+ *
+ * Sets the page orientation of the `GtkPageSetup`.
+ */
+void
+gtk_page_setup_set_orientation (GtkPageSetup       *setup,
+                               GtkPageOrientation  orientation)
+{
+  setup->orientation = orientation;
+}
+
+/**
+ * gtk_page_setup_get_paper_size:
+ * @setup: a `GtkPageSetup`
+ *
+ * Gets the paper size of the `GtkPageSetup`.
+ *
+ * Returns: (transfer none): the paper size
+ */
+GtkPaperSize *
+gtk_page_setup_get_paper_size (GtkPageSetup *setup)
+{
+  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), NULL);
+
+  return setup->paper_size;
+}
+
+/**
+ * gtk_page_setup_set_paper_size:
+ * @setup: a `GtkPageSetup`
+ * @size: a `GtkPaperSize`
+ *
+ * Sets the paper size of the `GtkPageSetup` without
+ * changing the margins.
+ *
+ * See [method@Gtk.PageSetup.set_paper_size_and_default_margins].
+ */
+void
+gtk_page_setup_set_paper_size (GtkPageSetup *setup,
+                              GtkPaperSize *size)
+{
+  GtkPaperSize *old_size;
+
+  g_return_if_fail (GTK_IS_PAGE_SETUP (setup));
+  g_return_if_fail (size != NULL);
+
+  old_size = setup->paper_size;
+
+  setup->paper_size = gtk_paper_size_copy (size);
+
+  if (old_size)
+    gtk_paper_size_free (old_size);
+}
+
+/**
+ * gtk_page_setup_set_paper_size_and_default_margins:
+ * @setup: a `GtkPageSetup`
+ * @size: a `GtkPaperSize`
+ *
+ * Sets the paper size of the `GtkPageSetup` and modifies
+ * the margins according to the new paper size.
+ */
+void
+gtk_page_setup_set_paper_size_and_default_margins (GtkPageSetup *setup,
+                                                  GtkPaperSize *size)
+{
+  gtk_page_setup_set_paper_size (setup, size);
+  setup->top_margin = gtk_paper_size_get_default_top_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->bottom_margin = gtk_paper_size_get_default_bottom_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->left_margin = gtk_paper_size_get_default_left_margin (setup->paper_size, GTK_UNIT_MM);
+  setup->right_margin = gtk_paper_size_get_default_right_margin (setup->paper_size, GTK_UNIT_MM);
+}
+
+/**
+ * gtk_page_setup_get_top_margin:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Gets the top margin in units of @unit.
+ *
+ * Returns: the top margin
+ */
+double
+gtk_page_setup_get_top_margin (GtkPageSetup *setup,
+                              GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (setup->top_margin, unit);
+}
+
+/**
+ * gtk_page_setup_set_top_margin:
+ * @setup: a `GtkPageSetup`
+ * @margin: the new top margin in units of @unit
+ * @unit: the units for @margin
+ *
+ * Sets the top margin of the `GtkPageSetup`.
+ */
+void
+gtk_page_setup_set_top_margin (GtkPageSetup *setup,
+                              double        margin,
+                              GtkUnit       unit)
+{
+  setup->top_margin = _gtk_print_convert_to_mm (margin, unit);
+}
+
+/**
+ * gtk_page_setup_get_bottom_margin:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Gets the bottom margin in units of @unit.
+ *
+ * Returns: the bottom margin
+ */
+double
+gtk_page_setup_get_bottom_margin (GtkPageSetup *setup,
+                                 GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (setup->bottom_margin, unit);
+}
+
+/**
+ * gtk_page_setup_set_bottom_margin:
+ * @setup: a `GtkPageSetup`
+ * @margin: the new bottom margin in units of @unit
+ * @unit: the units for @margin
+ *
+ * Sets the bottom margin of the `GtkPageSetup`.
+ */
+void
+gtk_page_setup_set_bottom_margin (GtkPageSetup *setup,
+                                 double        margin,
+                                 GtkUnit       unit)
+{
+  setup->bottom_margin = _gtk_print_convert_to_mm (margin, unit);
+}
+
+/**
+ * gtk_page_setup_get_left_margin:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Gets the left margin in units of @unit.
+ *
+ * Returns: the left margin
+ */
+double
+gtk_page_setup_get_left_margin (GtkPageSetup *setup,
+                               GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (setup->left_margin, unit);
+}
+
+/**
+ * gtk_page_setup_set_left_margin:
+ * @setup: a `GtkPageSetup`
+ * @margin: the new left margin in units of @unit
+ * @unit: the units for @margin
+ *
+ * Sets the left margin of the `GtkPageSetup`.
+ */
+void
+gtk_page_setup_set_left_margin (GtkPageSetup *setup,
+                               double        margin,
+                               GtkUnit       unit)
+{
+  setup->left_margin = _gtk_print_convert_to_mm (margin, unit);
+}
+
+/**
+ * gtk_page_setup_get_right_margin:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Gets the right margin in units of @unit.
+ *
+ * Returns: the right margin
+ */
+double
+gtk_page_setup_get_right_margin (GtkPageSetup *setup,
+                                GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (setup->right_margin, unit);
+}
+
+/**
+ * gtk_page_setup_set_right_margin:
+ * @setup: a `GtkPageSetup`
+ * @margin: the new right margin in units of @unit
+ * @unit: the units for @margin
+ *
+ * Sets the right margin of the `GtkPageSetup`.
+ */
+void
+gtk_page_setup_set_right_margin (GtkPageSetup *setup,
+                                double        margin,
+                                GtkUnit       unit)
+{
+  setup->right_margin = _gtk_print_convert_to_mm (margin, unit);
+}
+
+/**
+ * gtk_page_setup_get_paper_width:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Returns the paper width in units of @unit.
+ *
+ * Note that this function takes orientation,
+ * but not margins into consideration.
+ * See [method@Gtk.PageSetup.get_page_width].
+ *
+ * Returns: the paper width.
+ */
+double
+gtk_page_setup_get_paper_width (GtkPageSetup *setup,
+                               GtkUnit       unit)
+{
+  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+    return gtk_paper_size_get_width (setup->paper_size, unit);
+  else
+    return gtk_paper_size_get_height (setup->paper_size, unit);
+}
+
+/**
+ * gtk_page_setup_get_paper_height:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Returns the paper height in units of @unit.
+ *
+ * Note that this function takes orientation,
+ * but not margins into consideration.
+ * See [method@Gtk.PageSetup.get_page_height].
+ *
+ * Returns: the paper height.
+ */
+double
+gtk_page_setup_get_paper_height (GtkPageSetup *setup,
+                                GtkUnit       unit)
+{
+  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+    return gtk_paper_size_get_height (setup->paper_size, unit);
+  else
+    return gtk_paper_size_get_width (setup->paper_size, unit);
+}
+
+/**
+ * gtk_page_setup_get_page_width:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Returns the page width in units of @unit.
+ *
+ * Note that this function takes orientation
+ * and margins into consideration.
+ * See [method@Gtk.PageSetup.get_paper_width].
+ *
+ * Returns: the page width.
+ */
+double
+gtk_page_setup_get_page_width (GtkPageSetup *setup,
+                              GtkUnit       unit)
+{
+  double width;
+
+  width = gtk_page_setup_get_paper_width (setup, GTK_UNIT_MM);
+  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+    width -= setup->left_margin + setup->right_margin;
+  else
+    width -= setup->top_margin + setup->bottom_margin;
+
+  return _gtk_print_convert_from_mm (width, unit);
+}
+
+/**
+ * gtk_page_setup_get_page_height:
+ * @setup: a `GtkPageSetup`
+ * @unit: the unit for the return value
+ *
+ * Returns the page height in units of @unit.
+ *
+ * Note that this function takes orientation
+ * and margins into consideration.
+ * See [method@Gtk.PageSetup.get_paper_height].
+ *
+ * Returns: the page height.
+ */
+double
+gtk_page_setup_get_page_height (GtkPageSetup *setup,
+                               GtkUnit       unit)
+{
+  double height;
+
+  height = gtk_page_setup_get_paper_height (setup, GTK_UNIT_MM);
+  if (setup->orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+      setup->orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+    height -= setup->top_margin + setup->bottom_margin;
+  else
+    height -= setup->left_margin + setup->right_margin;
+
+  return _gtk_print_convert_from_mm (height, unit);
+}
+
+/**
+ * gtk_page_setup_load_file:
+ * @setup: a `GtkPageSetup`
+ * @file_name: (type filename): the filename to read the page setup from
+ * @error: (nullable): return location for an error
+ *
+ * Reads the page setup from the file @file_name.
+ *
+ * See [method@Gtk.PageSetup.to_file].
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_page_setup_load_file (GtkPageSetup *setup,
+                          const char   *file_name,
+                         GError      **error)
+{
+  gboolean retval = FALSE;
+  GKeyFile *key_file;
+
+  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
+  g_return_val_if_fail (file_name != NULL, FALSE);
+
+  key_file = g_key_file_new ();
+
+  if (g_key_file_load_from_file (key_file, file_name, 0, error) &&
+      gtk_page_setup_load_key_file (setup, key_file, NULL, error))
+    retval = TRUE;
+
+  g_key_file_free (key_file);
+
+  return retval;
+}
+
+/**
+ * gtk_page_setup_new_from_file:
+ * @file_name: (type filename): the filename to read the page setup from
+ * @error: (nullable): return location for an error
+ *
+ * Reads the page setup from the file @file_name.
+ *
+ * Returns a new `GtkPageSetup` object with the restored
+ * page setup, or %NULL if an error occurred.
+ * See [method@Gtk.PageSetup.to_file].
+ *
+ * Returns: the restored `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_page_setup_new_from_file (const char   *file_name,
+                             GError      **error)
+{
+  GtkPageSetup *setup = gtk_page_setup_new ();
+
+  if (!gtk_page_setup_load_file (setup, file_name, error))
+    {
+      g_object_unref (setup);
+      setup = NULL;
+    }
+
+  return setup;
+}
+
+/* something like this should really be in gobject! */
+static guint
+string_to_enum (GType type,
+                const char *enum_string)
+{
+  GEnumClass *enum_class;
+  const GEnumValue *value;
+  guint retval = 0;
+
+  g_return_val_if_fail (enum_string != NULL, 0);
+
+  enum_class = g_type_class_ref (type);
+  value = g_enum_get_value_by_nick (enum_class, enum_string);
+  if (value)
+    retval = value->value;
+
+  g_type_class_unref (enum_class);
+
+  return retval;
+}
+
+/**
+ * gtk_page_setup_load_key_file:
+ * @setup: a `GtkPageSetup`
+ * @key_file: the `GKeyFile` to retrieve the page_setup from
+ * @group_name: (nullable): the name of the group in the key_file to read
+ *   to use the default name “Page Setup”
+ * @error: (nullable): return location for an error
+ *
+ * Reads the page setup from the group @group_name in the key file
+ * @key_file.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_page_setup_load_key_file (GtkPageSetup *setup,
+                              GKeyFile     *key_file,
+                              const char   *group_name,
+                              GError      **error)
+{
+  GtkPaperSize *paper_size;
+  double top, bottom, left, right;
+  char *orientation = NULL, *freeme = NULL;
+  gboolean retval = FALSE;
+  GError *err = NULL;
+
+  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
+  g_return_val_if_fail (key_file != NULL, FALSE);
+
+  if (!group_name)
+    group_name = KEYFILE_GROUP_NAME;
+
+  if (!g_key_file_has_group (key_file, group_name))
+    {
+      g_set_error_literal (error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_INVALID_FILE,
+                           _("Not a valid page setup file"));
+      goto out;
+    }
+
+#define GET_DOUBLE(kf, group, name, v) \
+  v = g_key_file_get_double (kf, group, name, &err); \
+  if (err != NULL) \
+    { \
+      g_propagate_error (error, err);\
+      goto out;\
+    }
+
+  GET_DOUBLE (key_file, group_name, "MarginTop", top);
+  GET_DOUBLE (key_file, group_name, "MarginBottom", bottom);
+  GET_DOUBLE (key_file, group_name, "MarginLeft", left);
+  GET_DOUBLE (key_file, group_name, "MarginRight", right);
+
+#undef GET_DOUBLE
+
+  paper_size = gtk_paper_size_new_from_key_file (key_file, group_name, &err);
+  if (!paper_size)
+    {
+      g_propagate_error (error, err);
+      goto out;
+    }
+
+  gtk_page_setup_set_paper_size (setup, paper_size);
+  gtk_paper_size_free (paper_size);
+
+  gtk_page_setup_set_top_margin (setup, top, GTK_UNIT_MM);
+  gtk_page_setup_set_bottom_margin (setup, bottom, GTK_UNIT_MM);
+  gtk_page_setup_set_left_margin (setup, left, GTK_UNIT_MM);
+  gtk_page_setup_set_right_margin (setup, right, GTK_UNIT_MM);
+
+  orientation = g_key_file_get_string (key_file, group_name,
+                                      "Orientation", NULL);
+  if (orientation)
+    {
+      gtk_page_setup_set_orientation (setup,
+                                     string_to_enum (GTK_TYPE_PAGE_ORIENTATION,
+                                                     orientation));
+      g_free (orientation);
+    }
+
+  retval = TRUE;
+
+out:
+  g_free (freeme);
+  return retval;
+}
+
+/**
+ * gtk_page_setup_new_from_key_file:
+ * @key_file: the `GKeyFile` to retrieve the page_setup from
+ * @group_name: (nullable): the name of the group in the key_file to read
+ *    to use the default name “Page Setup”
+ * @error: (nullable): return location for an error
+ *
+ * Reads the page setup from the group @group_name in the key file
+ * @key_file.
+ *
+ * Returns a new `GtkPageSetup` object with the restored
+ * page setup, or %NULL if an error occurred.
+ *
+ * Returns: the restored `GtkPageSetup`
+ */
+GtkPageSetup *
+gtk_page_setup_new_from_key_file (GKeyFile     *key_file,
+                                 const char   *group_name,
+                                 GError      **error)
+{
+  GtkPageSetup *setup = gtk_page_setup_new ();
+
+  if (!gtk_page_setup_load_key_file (setup, key_file, group_name, error))
+    {
+      g_object_unref (setup);
+      setup = NULL;
+    }
+
+  return setup;
+}
+
+/**
+ * gtk_page_setup_to_file:
+ * @setup: a `GtkPageSetup`
+ * @file_name: (type filename): the file to save to
+ * @error: (nullable): return location for errors
+ *
+ * This function saves the information from @setup to @file_name.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_page_setup_to_file (GtkPageSetup  *setup,
+                       const char    *file_name,
+                       GError       **error)
+{
+  GKeyFile *key_file;
+  gboolean retval = FALSE;
+  char *data = NULL;
+  gsize len;
+
+  g_return_val_if_fail (GTK_IS_PAGE_SETUP (setup), FALSE);
+  g_return_val_if_fail (file_name != NULL, FALSE);
+
+  key_file = g_key_file_new ();
+  gtk_page_setup_to_key_file (setup, key_file, NULL);
+
+  data = g_key_file_to_data (key_file, &len, error);
+  if (!data)
+    goto out;
+
+  retval = g_file_set_contents (file_name, data, len, error);
+
+out:
+  g_key_file_free (key_file);
+  g_free (data);
+
+  return retval;
+}
+
+/* something like this should really be in gobject! */
+static char *
+enum_to_string (GType type,
+                guint enum_value)
+{
+  GEnumClass *enum_class;
+  GEnumValue *value;
+  char *retval = NULL;
+
+  enum_class = g_type_class_ref (type);
+
+  value = g_enum_get_value (enum_class, enum_value);
+  if (value)
+    retval = g_strdup (value->value_nick);
+
+  g_type_class_unref (enum_class);
+
+  return retval;
+}
+
+/**
+ * gtk_page_setup_to_key_file:
+ * @setup: a `GtkPageSetup`
+ * @key_file: the `GKeyFile` to save the page setup to
+ * @group_name: (nullable): the group to add the settings to in @key_file,
+ *   or %NULL to use the default name “Page Setup”
+ *
+ * This function adds the page setup from @setup to @key_file.
+ */
+void
+gtk_page_setup_to_key_file (GtkPageSetup *setup,
+                           GKeyFile     *key_file,
+                           const char   *group_name)
+{
+  GtkPaperSize *paper_size;
+  char *orientation;
+
+  g_return_if_fail (GTK_IS_PAGE_SETUP (setup));
+  g_return_if_fail (key_file != NULL);
+
+  if (!group_name)
+    group_name = KEYFILE_GROUP_NAME;
+
+  paper_size = gtk_page_setup_get_paper_size (setup);
+  g_assert (paper_size != NULL);
+
+  gtk_paper_size_to_key_file (paper_size, key_file, group_name);
+
+  g_key_file_set_double (key_file, group_name,
+                        "MarginTop", gtk_page_setup_get_top_margin (setup, GTK_UNIT_MM));
+  g_key_file_set_double (key_file, group_name,
+                        "MarginBottom", gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_MM));
+  g_key_file_set_double (key_file, group_name,
+                        "MarginLeft", gtk_page_setup_get_left_margin (setup, GTK_UNIT_MM));
+  g_key_file_set_double (key_file, group_name,
+                        "MarginRight", gtk_page_setup_get_right_margin (setup, GTK_UNIT_MM));
+
+  orientation = enum_to_string (GTK_TYPE_PAGE_ORIENTATION,
+                               gtk_page_setup_get_orientation (setup));
+  g_key_file_set_string (key_file, group_name,
+                        "Orientation", orientation);
+  g_free (orientation);
+}
+
+/**
+ * gtk_page_setup_to_gvariant:
+ * @setup: a `GtkPageSetup`
+ *
+ * Serialize page setup to an a{sv} variant.
+ *
+ * Return: (transfer none): a new, floating, `GVariant`
+ */
+GVariant *
+gtk_page_setup_to_gvariant (GtkPageSetup *setup)
+{
+  GtkPaperSize *paper_size;
+  GVariant *variant;
+  int i;
+  GVariantBuilder builder;
+  char *orientation;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+
+  paper_size = gtk_page_setup_get_paper_size (setup);
+
+  variant = g_variant_ref_sink (gtk_paper_size_to_gvariant (paper_size));
+  for (i = 0; i < g_variant_n_children (variant); i++)
+    g_variant_builder_add_value (&builder, g_variant_get_child_value (variant, i));
+  g_variant_unref (variant);
+
+  g_variant_builder_add (&builder, "{sv}", "MarginTop", g_variant_new_double (gtk_page_setup_get_top_margin (setup, GTK_UNIT_MM)));
+  g_variant_builder_add (&builder, "{sv}", "MarginBottom", g_variant_new_double (gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_MM)));
+  g_variant_builder_add (&builder, "{sv}", "MarginLeft", g_variant_new_double (gtk_page_setup_get_left_margin (setup, GTK_UNIT_MM)));
+  g_variant_builder_add (&builder, "{sv}", "MarginRight", g_variant_new_double (gtk_page_setup_get_right_margin (setup, GTK_UNIT_MM)));
+
+  orientation = enum_to_string (GTK_TYPE_PAGE_ORIENTATION,
+                                gtk_page_setup_get_orientation (setup));
+  g_variant_builder_add (&builder, "{sv}", "Orientation", g_variant_new_take_string (orientation));
+
+  return g_variant_builder_end (&builder);
+}
+
+/**
+ * gtk_page_setup_new_from_gvariant:
+ * @variant: an a{sv} `GVariant`
+ *
+ * Desrialize a page setup from an a{sv} variant.
+ *
+ * The variant must be in the format produced by
+ * [method@Gtk.PageSetup.to_gvariant].
+ *
+ * Returns: (transfer full): a new `GtkPageSetup` object
+ */
+GtkPageSetup *
+gtk_page_setup_new_from_gvariant (GVariant *variant)
+{
+  GtkPageSetup *setup;
+  const char *orientation;
+  double margin;
+  GtkPaperSize *paper_size;
+
+  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
+
+  setup = gtk_page_setup_new ();
+
+  paper_size = gtk_paper_size_new_from_gvariant (variant);
+  if (paper_size)
+    {
+      gtk_page_setup_set_paper_size (setup, paper_size);
+      gtk_paper_size_free (paper_size);
+    }
+
+  if (g_variant_lookup (variant, "MarginTop", "d", &margin))
+    gtk_page_setup_set_top_margin (setup, margin, GTK_UNIT_MM);
+  if (g_variant_lookup (variant, "MarginBottom", "d", &margin))
+    gtk_page_setup_set_bottom_margin (setup, margin, GTK_UNIT_MM);
+  if (g_variant_lookup (variant, "MarginLeft", "d", &margin))
+    gtk_page_setup_set_left_margin (setup, margin, GTK_UNIT_MM);
+  if (g_variant_lookup (variant, "MarginRight", "d", &margin))
+    gtk_page_setup_set_right_margin (setup, margin, GTK_UNIT_MM);
+
+  if (g_variant_lookup (variant, "Orientation", "&s", &orientation))
+    gtk_page_setup_set_orientation (setup, string_to_enum (GTK_TYPE_PAGE_ORIENTATION,
+                                                           orientation));
+
+  return setup;
+}
diff --git a/gtk/print/gtkpapersize.c b/gtk/print/gtkpapersize.c
new file mode 100644 (file)
index 0000000..97bd96d
--- /dev/null
@@ -0,0 +1,1118 @@
+/* GTK - The GIMP Toolkit
+ * gtkpapersize.c: Paper Size
+ * Copyright (C) 2006, Red Hat, Inc.
+ * 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 <string.h>
+#include <stdlib.h>
+#include <locale.h>
+#if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
+#include <langinfo.h>
+#endif
+#include <math.h>
+
+#include "gtkpapersize.h"
+#include "gtkprintutilsprivate.h"
+#include "gtkprintoperation.h"  /* for GtkPrintError */
+#include <glib/gi18n-lib.h>
+
+/* _gtk_load_custom_papers() only on Unix so far  */
+#ifdef G_OS_UNIX
+#include "gtkcustompaperunixdialog.h"
+#endif
+
+#include "paper_names_offsets.c"
+
+
+/**
+ * GtkPaperSize:
+ *
+ * `GtkPaperSize` handles paper sizes.
+ *
+ * It uses the standard called
+ * [PWG 5101.1-2002 PWG: Standard for Media Standardized Names](http://www.pwg.org/standards.html)
+ * to name the paper sizes (and to get the data for the page sizes).
+ * In addition to standard paper sizes, `GtkPaperSize` allows to
+ * construct custom paper sizes with arbitrary dimensions.
+ *
+ * The `GtkPaperSize` object stores not only the dimensions (width
+ * and height) of a paper size and its name, it also provides
+ * default print margins.
+ */
+
+
+struct _GtkPaperSize
+{
+  const PaperInfo *info;
+
+  /* If these are not set we fall back to info */
+  char *name;
+  char *display_name;
+  char *ppd_name;
+
+  double width, height; /* Stored in mm */
+  gboolean is_custom;
+  gboolean is_ipp;
+};
+
+G_DEFINE_BOXED_TYPE (GtkPaperSize, gtk_paper_size,
+                     gtk_paper_size_copy,
+                     gtk_paper_size_free)
+
+static const PaperInfo *
+lookup_paper_info (const char *name)
+{
+  int lower = 0;
+  int upper = G_N_ELEMENTS (standard_names_offsets) - 1;
+  int mid;
+  int cmp;
+
+  do
+    {
+       mid = (lower + upper) / 2;
+       cmp = strcmp (name, paper_names + standard_names_offsets[mid].name);
+       if (cmp < 0)
+         upper = mid - 1;
+       else if (cmp > 0)
+         lower = mid + 1;
+       else
+         return &standard_names_offsets[mid];
+    }
+  while (lower <= upper);
+
+  return NULL;
+}
+
+static gboolean
+parse_media_size (const char *size,
+                  double      *width_mm,
+                  double      *height_mm)
+{
+  const char *p;
+  char *e;
+  double short_dim, long_dim;
+
+  p = size;
+
+  short_dim = g_ascii_strtod (p, &e);
+
+  if (p == e || *e != 'x')
+    return FALSE;
+
+  p = e + 1; /* Skip x */
+
+  long_dim = g_ascii_strtod (p, &e);
+
+  if (p == e)
+    return FALSE;
+
+  p = e;
+
+  if (strcmp (p, "in") == 0)
+    {
+      short_dim = short_dim * MM_PER_INCH;
+      long_dim = long_dim * MM_PER_INCH;
+    }
+  else if (strcmp (p, "mm") != 0)
+    return FALSE;
+
+  if (width_mm)
+    *width_mm = short_dim;
+  if (height_mm)
+    *height_mm = long_dim;
+
+  return TRUE;
+}
+
+static gboolean
+parse_full_media_size_name (const char   *full_name,
+                            char        **name,
+                            double       *width_mm,
+                            double       *height_mm)
+{
+  const char *p;
+  const char *end_of_name;
+
+  /* From the spec:
+   media-size-self-describing-name =
+        ( class-in "_" size-name "_" short-dim "x" long-dim "in" ) |
+        ( class-mm "_" size-name "_" short-dim "x" long-dim "mm" )
+   class-in = "custom" | "na" | "asme" | "roc" | "oe"
+   class-mm = "custom" | "iso" | "jis" | "jpn" | "prc" | "om"
+   size-name = ( lowalpha | digit ) *( lowalpha | digit | "-" )
+   short-dim = dim
+   long-dim = dim
+   dim = integer-part [fraction-part] | "0" fraction-part
+   integer-part = non-zero-digit *digit
+   fraction-part = "." *digit non-zero-digit
+   lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+              "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+              "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
+   non-zero-digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+   digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+ */
+
+  p = strchr (full_name, '_');
+  if (p == NULL)
+    return FALSE;
+
+  p++; /* Skip _ */
+
+  p = strchr (p, '_');
+  if (p == NULL)
+    return FALSE;
+
+  end_of_name = p;
+
+  p++; /* Skip _ */
+
+  if (!parse_media_size (p, width_mm, height_mm))
+    return FALSE;
+
+  if (name)
+    *name = g_strndup (full_name, end_of_name - full_name);
+
+  return TRUE;
+}
+
+static GtkPaperSize *
+gtk_paper_size_new_from_info (const PaperInfo *info)
+{
+  GtkPaperSize *size;
+
+  size = g_new0 (GtkPaperSize, 1);
+  size->info = info;
+  size->width = info->width;
+  size->height = info->height;
+
+  return size;
+}
+
+/**
+ * gtk_paper_size_new:
+ * @name: (nullable): a paper size name
+ *
+ * Creates a new `GtkPaperSize` object by parsing a
+ * [PWG 5101.1-2002](ftp://ftp.pwg.org/pub/pwg/candidates/cs-pwgmsn10-20020226-5101.1.pdf)
+ * paper name.
+ *
+ * If @name is %NULL, the default paper size is returned,
+ * see [func@Gtk.PaperSize.get_default].
+ *
+ * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
+ * to free it
+ */
+GtkPaperSize *
+gtk_paper_size_new (const char *name)
+{
+  GtkPaperSize *size;
+  char *short_name;
+  double width, height;
+  const PaperInfo *info;
+
+  if (name == NULL)
+    name = gtk_paper_size_get_default ();
+
+  if (parse_full_media_size_name (name, &short_name, &width, &height))
+    {
+      info = lookup_paper_info (short_name);
+      if (info != NULL && info->width == width && info->height == height)
+        {
+          size = gtk_paper_size_new_from_info (info);
+          g_free (short_name);
+        }
+      else
+        {
+          size = g_new0 (GtkPaperSize, 1);
+
+          size->width = width;
+          size->height = height;
+          size->name = short_name;
+          size->display_name = g_strdup (short_name);
+          if (strncmp (short_name, "custom", 6) == 0)
+            size->is_custom = TRUE;
+        }
+    }
+  else
+    {
+      info = lookup_paper_info (name);
+      if (info != NULL)
+        size = gtk_paper_size_new_from_info (info);
+      else
+        {
+          g_warning ("Unknown paper size %s", name);
+          size = g_new0 (GtkPaperSize, 1);
+          size->name = g_strdup (name);
+          size->display_name = g_strdup (name);
+          /* Default to A4 size */
+          size->width = 210;
+          size->height = 297;
+        }
+    }
+
+  return size;
+}
+
+static char *
+improve_displayname (const char *name)
+{
+  char *p, *p1, *p2, *s;
+
+  p = strrchr (name, 'x');
+  if (p && p != name &&
+      g_ascii_isdigit (*(p - 1)) &&
+      g_ascii_isdigit (*(p + 1)))
+    {
+      p1 = g_strndup (name, p - name);
+      p2 = g_strdup (p + 1);
+      s = g_strconcat (p1, "×", p2, NULL);
+      g_free (p1);
+      g_free (p2);
+    }
+  else
+    s = g_strdup (name);
+
+  return s;
+}
+
+/**
+ * gtk_paper_size_new_from_ppd:
+ * @ppd_name: a PPD paper name
+ * @ppd_display_name: the corresponding human-readable name
+ * @width: the paper width, in points
+ * @height: the paper height in points
+ *
+ * Creates a new `GtkPaperSize` object by using
+ * PPD information.
+ *
+ * If @ppd_name is not a recognized PPD paper name,
+ * @ppd_display_name, @width and @height are used to
+ * construct a custom `GtkPaperSize` object.
+ *
+ * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
+ * to free it
+ */
+GtkPaperSize *
+gtk_paper_size_new_from_ppd (const char *ppd_name,
+                             const char *ppd_display_name,
+                             double       width,
+                             double       height)
+{
+  char *name;
+  const char *lookup_ppd_name;
+  char *freeme;
+  GtkPaperSize *size;
+  int i;
+  char *display_name;
+
+  lookup_ppd_name = ppd_name;
+
+  freeme = NULL;
+  /* Strip out Traverse suffix in matching. */
+  if (g_str_has_suffix (ppd_name, ".Transverse"))
+    {
+      lookup_ppd_name = freeme =
+        g_strndup (ppd_name, strlen (ppd_name) - strlen (".Transverse"));
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
+    {
+      if (standard_names_offsets[i].ppd_name != -1 &&
+          strcmp (paper_names + standard_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
+        {
+          size = gtk_paper_size_new_from_info (&standard_names_offsets[i]);
+          goto out;
+        }
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (extra_ppd_names_offsets); i++)
+    {
+      if (strcmp (paper_names + extra_ppd_names_offsets[i].ppd_name, lookup_ppd_name) == 0)
+        {
+          size = gtk_paper_size_new (paper_names + extra_ppd_names_offsets[i].standard_name);
+          goto out;
+        }
+    }
+
+  name = g_strconcat ("ppd_", ppd_name, NULL);
+  display_name = improve_displayname (ppd_display_name);
+  size = gtk_paper_size_new_custom (name, display_name, width, height, GTK_UNIT_POINTS);
+  g_free (display_name);
+  g_free (name);
+
+ out:
+
+  if (size->info == NULL ||
+      size->info->ppd_name == -1 ||
+      strcmp (paper_names + size->info->ppd_name, ppd_name) != 0)
+    size->ppd_name = g_strdup (ppd_name);
+
+  g_free (freeme);
+
+  return size;
+}
+
+/* Tolerance of paper size in points according to PostScript Language Reference */
+#define PAPER_SIZE_TOLERANCE 5
+
+/**
+ * gtk_paper_size_new_from_ipp:
+ * @ipp_name: an IPP paper name
+ * @width: the paper width, in points
+ * @height: the paper height in points
+ *
+ * Creates a new `GtkPaperSize` object by using
+ * IPP information.
+ *
+ * If @ipp_name is not a recognized paper name,
+ * @width and @height are used to
+ * construct a custom `GtkPaperSize` object.
+ *
+ * Returns: a new `GtkPaperSize`, use [method@Gtk.PaperSize.free]
+ * to free it
+ */
+GtkPaperSize *
+gtk_paper_size_new_from_ipp (const char *ipp_name,
+                             double       width,
+                             double       height)
+{
+  GtkPaperSize *size;
+  const char   *name = NULL;
+  gboolean      found = FALSE;
+  float         x_dimension;
+  float         y_dimension;
+  char         *display_name = NULL;
+  int           i;
+
+  /* Find paper size according to its name */
+  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
+    {
+      if (standard_names_offsets[i].name != -1)
+        name = paper_names + standard_names_offsets[i].name;
+      if (name != NULL &&
+          /* Given paper size name is equal to a name
+             from the standard paper size names list. */
+          ((g_strcmp0 (ipp_name, name) == 0) ||
+           /* Given paper size name is prefixed by a name
+              from the standard paper size names list +
+              it consists of size in its name (e.g. iso_a4_210x297mm). */
+            (g_str_has_prefix (ipp_name, name) &&
+             strlen (ipp_name) > strlen (name) + 2 &&
+             ipp_name[strlen (ipp_name)] == '_' &&
+             g_ascii_isdigit (ipp_name[strlen (ipp_name) + 1]) &&
+             (g_str_has_suffix (ipp_name, "mm") ||
+              g_str_has_suffix (ipp_name, "in")))))
+        {
+          display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,
+                                                 "paper size",
+                                                 paper_names + standard_names_offsets[i].display_name));
+          found = TRUE;
+          break;
+        }
+    }
+
+  /* Find paper size according to its size */
+  if (display_name == NULL)
+    {
+      for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); i++)
+        {
+          x_dimension = _gtk_print_convert_from_mm (standard_names_offsets[i].width, GTK_UNIT_POINTS);
+          y_dimension = _gtk_print_convert_from_mm (standard_names_offsets[i].height, GTK_UNIT_POINTS);
+
+          if (fabs (x_dimension - width) <= PAPER_SIZE_TOLERANCE &&
+              fabs (y_dimension - height) <= PAPER_SIZE_TOLERANCE)
+            {
+              display_name = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,
+                                                     "paper size",
+                                                     paper_names + standard_names_offsets[i].display_name));
+              found = TRUE;
+              break;
+            }
+        }
+    }
+
+  /* Fallback to name of the paper size as given in "ipp_name" parameter */
+  if (display_name == NULL)
+    display_name = g_strdup (ipp_name);
+
+  size = gtk_paper_size_new_custom (ipp_name, display_name, width, height, GTK_UNIT_POINTS);
+  size->is_custom = !found;
+  size->is_ipp = found;
+
+  g_free (display_name);
+
+  return size;
+}
+
+/**
+ * gtk_paper_size_new_custom:
+ * @name: the paper name
+ * @display_name: the human-readable name
+ * @width: the paper width, in units of @unit
+ * @height: the paper height, in units of @unit
+ * @unit: the unit for @width and @height. not %GTK_UNIT_NONE.
+ *
+ * Creates a new `GtkPaperSize` object with the
+ * given parameters.
+ *
+ * Returns: a new `GtkPaperSize` object, use [method@Gtk.PaperSize.free]
+ * to free it
+ */
+GtkPaperSize *
+gtk_paper_size_new_custom (const char *name,
+                           const char *display_name,
+                           double       width,
+                           double       height,
+                           GtkUnit      unit)
+{
+  GtkPaperSize *size;
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (unit != GTK_UNIT_NONE, NULL);
+
+  size = g_new0 (GtkPaperSize, 1);
+
+  size->name = g_strdup (name);
+  size->display_name = g_strdup (display_name);
+  size->is_custom = TRUE;
+
+  size->width = _gtk_print_convert_to_mm (width, unit);
+  size->height = _gtk_print_convert_to_mm (height, unit);
+
+  return size;
+}
+
+/**
+ * gtk_paper_size_copy:
+ * @other: a `GtkPaperSize`
+ *
+ * Copies an existing `GtkPaperSize`.
+ *
+ * Returns: a copy of @other
+ */
+GtkPaperSize *
+gtk_paper_size_copy (GtkPaperSize *other)
+{
+  GtkPaperSize *size;
+
+  size = g_new0 (GtkPaperSize, 1);
+
+  size->info = other->info;
+  if (other->name)
+    size->name = g_strdup (other->name);
+  if (other->display_name)
+    size->display_name = g_strdup (other->display_name);
+  if (other->ppd_name)
+    size->ppd_name = g_strdup (other->ppd_name);
+
+  size->width = other->width;
+  size->height = other->height;
+  size->is_custom = other->is_custom;
+  size->is_ipp = other->is_ipp;
+
+  return size;
+}
+
+/**
+ * gtk_paper_size_free:
+ * @size: a `GtkPaperSize`
+ *
+ * Free the given `GtkPaperSize` object.
+ */
+void
+gtk_paper_size_free (GtkPaperSize *size)
+{
+  g_free (size->name);
+  g_free (size->display_name);
+  g_free (size->ppd_name);
+  g_free (size);
+}
+
+/**
+ * gtk_paper_size_is_equal:
+ * @size1: a `GtkPaperSize` object
+ * @size2: another `GtkPaperSize` object
+ *
+ * Compares two `GtkPaperSize` objects.
+ *
+ * Returns: %TRUE, if @size1 and @size2
+ * represent the same paper size
+ */
+gboolean
+gtk_paper_size_is_equal (GtkPaperSize *size1,
+                         GtkPaperSize *size2)
+{
+  if (size1->info != NULL && size2->info != NULL)
+    return size1->info == size2->info;
+
+  return strcmp (gtk_paper_size_get_name (size1),
+                 gtk_paper_size_get_name (size2)) == 0;
+}
+
+/**
+ * gtk_paper_size_get_paper_sizes:
+ * @include_custom: whether to include custom paper sizes
+ *   as defined in the page setup dialog
+ *
+ * Creates a list of known paper sizes.
+ *
+ * Returns:  (element-type GtkPaperSize) (transfer full): a newly allocated list of newly
+ *    allocated `GtkPaperSize` objects
+ */
+GList *
+gtk_paper_size_get_paper_sizes (gboolean include_custom)
+{
+  GList *list = NULL;
+  guint i;
+/* _gtk_load_custom_papers() only on Unix so far  */
+#ifdef G_OS_UNIX
+  if (include_custom)
+    {
+      GList *page_setups, *l;
+
+      page_setups = _gtk_load_custom_papers ();
+      for (l = page_setups; l != NULL; l = l->next)
+        {
+          GtkPageSetup *setup = (GtkPageSetup *) l->data;
+          GtkPaperSize *size;
+
+          size = gtk_page_setup_get_paper_size (setup);
+          list = g_list_prepend (list, gtk_paper_size_copy (size));
+        }
+
+      g_list_free_full (page_setups, g_object_unref);
+    }
+#endif
+  for (i = 0; i < G_N_ELEMENTS (standard_names_offsets); ++i)
+    {
+       GtkPaperSize *size;
+
+       size = gtk_paper_size_new_from_info (&standard_names_offsets[i]);
+       list = g_list_prepend (list, size);
+    }
+
+  return g_list_reverse (list);
+}
+
+
+/**
+ * gtk_paper_size_get_name:
+ * @size: a `GtkPaperSize` object
+ *
+ * Gets the name of the `GtkPaperSize`.
+ *
+ * Returns: the name of @size
+ */
+const char *
+gtk_paper_size_get_name (GtkPaperSize *size)
+{
+  if (size->name)
+    return size->name;
+  g_assert (size->info != NULL);
+  return paper_names + size->info->name;
+}
+
+/**
+ * gtk_paper_size_get_display_name:
+ * @size: a `GtkPaperSize` object
+ *
+ * Gets the human-readable name of the `GtkPaperSize`.
+ *
+ * Returns: the human-readable name of @size
+ */
+const char *
+gtk_paper_size_get_display_name (GtkPaperSize *size)
+{
+  const char *display_name;
+
+  if (size->display_name)
+    return size->display_name;
+
+  g_assert (size->info != NULL);
+
+  display_name = paper_names + size->info->display_name;
+  return g_dpgettext2 (GETTEXT_PACKAGE, "paper size", display_name);
+}
+
+/**
+ * gtk_paper_size_get_ppd_name:
+ * @size: a `GtkPaperSize` object
+ *
+ * Gets the PPD name of the `GtkPaperSize`, which
+ * may be %NULL.
+ *
+ * Returns: the PPD name of @size
+ */
+const char *
+gtk_paper_size_get_ppd_name (GtkPaperSize *size)
+{
+  if (size->ppd_name)
+    return size->ppd_name;
+  if (size->info)
+    return paper_names + size->info->ppd_name;
+  return NULL;
+}
+
+/**
+ * gtk_paper_size_get_width:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the paper width of the `GtkPaperSize`, in
+ * units of @unit.
+ *
+ * Returns: the paper width
+ */
+double
+gtk_paper_size_get_width (GtkPaperSize *size,
+                          GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (size->width, unit);
+}
+
+/**
+ * gtk_paper_size_get_height:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the paper height of the `GtkPaperSize`, in
+ * units of @unit.
+ *
+ * Returns: the paper height
+ */
+double
+gtk_paper_size_get_height (GtkPaperSize *size,
+                           GtkUnit       unit)
+{
+  return _gtk_print_convert_from_mm (size->height, unit);
+}
+
+/**
+ * gtk_paper_size_is_custom:
+ * @size: a `GtkPaperSize` object
+ *
+ * Returns %TRUE if @size is not a standard paper size.
+ *
+ * Returns: whether @size is a custom paper size.
+ **/
+gboolean
+gtk_paper_size_is_custom (GtkPaperSize *size)
+{
+  return size->is_custom;
+}
+
+/**
+ * gtk_paper_size_is_ipp:
+ * @size: a `GtkPaperSize` object
+ *
+ * Returns %TRUE if @size is an IPP standard paper size.
+ *
+ * Returns: whether @size is not an IPP custom paper size.
+ **/
+gboolean
+gtk_paper_size_is_ipp (GtkPaperSize *size)
+{
+  return size->is_ipp;
+}
+
+/**
+ * gtk_paper_size_set_size:
+ * @size: a custom `GtkPaperSize` object
+ * @width: the new width in units of @unit
+ * @height: the new height in units of @unit
+ * @unit: the unit for @width and @height
+ *
+ * Changes the dimensions of a @size to @width x @height.
+ */
+void
+gtk_paper_size_set_size (GtkPaperSize *size,
+                         double        width,
+                         double        height,
+                         GtkUnit       unit)
+{
+  g_return_if_fail (size != NULL);
+  g_return_if_fail (size->is_custom);
+
+  size->width = _gtk_print_convert_to_mm (width, unit);
+  size->height = _gtk_print_convert_to_mm (height, unit);
+}
+
+#define NL_PAPER_GET(x)         \
+  ((union { char *string; unsigned int word; })nl_langinfo(x)).word
+
+/**
+ * gtk_paper_size_get_default:
+ *
+ * Returns the name of the default paper size, which
+ * depends on the current locale.
+ *
+ * Returns: the name of the default paper size. The string
+ * is owned by GTK and should not be modified.
+ */
+const char *
+gtk_paper_size_get_default (void)
+{
+  char *locale, *freeme = NULL;
+  const char *paper_size;
+
+#if defined(HAVE__NL_PAPER_HEIGHT) && defined(HAVE__NL_PAPER_WIDTH)
+  {
+    int width = NL_PAPER_GET (_NL_PAPER_WIDTH);
+    int height = NL_PAPER_GET (_NL_PAPER_HEIGHT);
+
+    if (width == 210 && height == 297)
+      return GTK_PAPER_NAME_A4;
+
+    if (width == 216 && height == 279)
+      return GTK_PAPER_NAME_LETTER;
+  }
+#endif
+
+#ifdef G_OS_WIN32
+  freeme = locale = g_win32_getlocale ();
+#elif defined(LC_PAPER)
+  locale = setlocale(LC_PAPER, NULL);
+#else
+  locale = setlocale(LC_MESSAGES, NULL);
+#endif
+
+  if (!locale)
+    return GTK_PAPER_NAME_A4;
+
+  /* CLDR 1.8.1
+   * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/territory_language_information.html
+   */
+  if (g_regex_match_simple("[^_.@]{2,3}_(BZ|CA|CL|CO|CR|GT|MX|NI|PA|PH|PR|SV|US|VE)",
+                           locale, G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED))
+    paper_size = GTK_PAPER_NAME_LETTER;
+  else
+    paper_size = GTK_PAPER_NAME_A4;
+
+  g_free (freeme);
+  return paper_size;
+}
+
+/* These get the default margins used for the paper size. Its
+ * larger than most printers margins, so that it will be within
+ * the imageble area on any printer.
+ *
+ * I’ve taken the actual values used from the OSX page setup dialog.
+ * I’m not sure exactly where they got these values for, but might
+ * correspond to this (from ghostscript docs):
+ *
+ * All DeskJets have 0.5 inches (1.27cm) of unprintable bottom margin,
+ * due to the mechanical arrangement used to grab the paper. Side margins
+ * are approximately 0.25 inches (0.64cm) for U.S. letter paper, and 0.15
+ * inches (0.38cm) for A4.
+ */
+
+/**
+ * gtk_paper_size_get_default_top_margin:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the default top margin for the `GtkPaperSize`.
+ *
+ * Returns: the default top margin
+ */
+double
+gtk_paper_size_get_default_top_margin (GtkPaperSize *size,
+                                       GtkUnit       unit)
+{
+  double margin;
+
+  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
+  return _gtk_print_convert_from_mm (margin, unit);
+}
+
+/**
+ * gtk_paper_size_get_default_bottom_margin:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the default bottom margin for the `GtkPaperSize`.
+ *
+ * Returns: the default bottom margin
+ */
+double
+gtk_paper_size_get_default_bottom_margin (GtkPaperSize *size,
+                                          GtkUnit       unit)
+{
+  double margin;
+  const char *name;
+
+  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
+
+  name = gtk_paper_size_get_name (size);
+  if (strcmp (name, "na_letter") == 0 ||
+      strcmp (name, "na_legal") == 0 ||
+      strcmp (name, "iso_a4") == 0)
+    margin = _gtk_print_convert_to_mm (0.56, GTK_UNIT_INCH);
+
+  return _gtk_print_convert_from_mm (margin, unit);
+}
+
+/**
+ * gtk_paper_size_get_default_left_margin:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the default left margin for the `GtkPaperSize`.
+ *
+ * Returns: the default left margin
+ */
+double
+gtk_paper_size_get_default_left_margin (GtkPaperSize *size,
+                                        GtkUnit       unit)
+{
+  double margin;
+
+  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
+  return _gtk_print_convert_from_mm (margin, unit);
+}
+
+/**
+ * gtk_paper_size_get_default_right_margin:
+ * @size: a `GtkPaperSize` object
+ * @unit: the unit for the return value, not %GTK_UNIT_NONE
+ *
+ * Gets the default right margin for the `GtkPaperSize`.
+ *
+ * Returns: the default right margin
+ */
+double
+gtk_paper_size_get_default_right_margin (GtkPaperSize *size,
+                                         GtkUnit       unit)
+{
+  double margin;
+
+  margin = _gtk_print_convert_to_mm (0.25, GTK_UNIT_INCH);
+  return _gtk_print_convert_from_mm (margin, unit);
+}
+
+/**
+ * gtk_paper_size_new_from_key_file:
+ * @key_file: the `GKeyFile` to retrieve the papersize from
+ * @group_name: (nullable): the name of the group in the key file to read,
+ *   or %NULL to read the first group
+ * @error: (nullable): return location for an error
+ *
+ * Reads a paper size from the group @group_name in the key file
+ * @key_file.
+ *
+ * Returns: a new `GtkPaperSize` object with the restored paper size
+ */
+GtkPaperSize *
+gtk_paper_size_new_from_key_file (GKeyFile     *key_file,
+                                  const char   *group_name,
+                                  GError      **error)
+{
+  GtkPaperSize *paper_size = NULL;
+  char *name = NULL;
+  char *ppd_name = NULL;
+  char *display_name = NULL;
+  char *freeme = NULL;
+  double width, height;
+  GError *err = NULL;
+
+  g_return_val_if_fail (key_file != NULL, NULL);
+
+  if (!group_name)
+    group_name = freeme = g_key_file_get_start_group (key_file);
+  if (!group_name || !g_key_file_has_group (key_file, group_name))
+    {
+      g_set_error_literal (error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_INVALID_FILE,
+                           _("Not a valid page setup file"));
+      goto out;
+    }
+
+#define GET_DOUBLE(kf, group, name, v) \
+  v = g_key_file_get_double (kf, group, name, &err); \
+  if (err != NULL) \
+    {\
+      g_propagate_error (error, err);\
+      goto out;\
+    }
+
+  GET_DOUBLE (key_file, group_name, "Width", width);
+  GET_DOUBLE (key_file, group_name, "Height", height);
+
+#undef GET_DOUBLE
+
+  name = g_key_file_get_string (key_file, group_name,
+                                "Name", NULL);
+  ppd_name = g_key_file_get_string (key_file, group_name,
+                                    "PPDName", NULL);
+  display_name = g_key_file_get_string (key_file, group_name,
+                                        "DisplayName", NULL);
+  /* Fallback for old ~/.gtk-custom-paper entries */
+  if (!display_name)
+    display_name = g_strdup (name);
+
+  if (ppd_name != NULL)
+    paper_size = gtk_paper_size_new_from_ppd (ppd_name,
+                                              display_name,
+                                              _gtk_print_convert_from_mm (width, GTK_UNIT_POINTS),
+                                              _gtk_print_convert_from_mm (height, GTK_UNIT_POINTS));
+  else if (name != NULL)
+    paper_size = gtk_paper_size_new_custom (name, display_name,
+                                            width, height, GTK_UNIT_MM);
+  else
+    {
+      g_set_error_literal (error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_INVALID_FILE,
+                           _("Not a valid page setup file"));
+      goto out;
+    }
+
+  g_assert (paper_size != NULL);
+
+out:
+  g_free (ppd_name);
+  g_free (name);
+  g_free (display_name);
+  g_free (freeme);
+
+  return paper_size;
+}
+
+/**
+ * gtk_paper_size_to_key_file:
+ * @size: a `GtkPaperSize`
+ * @key_file: the `GKeyFile` to save the paper size to
+ * @group_name: the group to add the settings to in @key_file
+ *
+ * This function adds the paper size from @size to @key_file.
+ */
+void
+gtk_paper_size_to_key_file (GtkPaperSize *size,
+                            GKeyFile     *key_file,
+                            const char   *group_name)
+{
+  const char *name, *ppd_name, *display_name;
+
+  g_return_if_fail (size != NULL);
+  g_return_if_fail (key_file != NULL);
+
+  name = gtk_paper_size_get_name (size);
+  display_name = gtk_paper_size_get_display_name (size);
+  ppd_name = gtk_paper_size_get_ppd_name (size);
+
+  if (ppd_name != NULL)
+    g_key_file_set_string (key_file, group_name,
+                           "PPDName", ppd_name);
+  else
+    g_key_file_set_string (key_file, group_name,
+                           "Name", name);
+
+  if (display_name)
+    g_key_file_set_string (key_file, group_name,
+                           "DisplayName", display_name);
+
+  g_key_file_set_double (key_file, group_name,
+                         "Width", gtk_paper_size_get_width (size, GTK_UNIT_MM));
+  g_key_file_set_double (key_file, group_name,
+                         "Height", gtk_paper_size_get_height (size, GTK_UNIT_MM));
+}
+
+/**
+ * gtk_paper_size_to_gvariant:
+ * @paper_size: a `GtkPaperSize`
+ *
+ * Serialize a paper size to an `a{sv}` variant.
+ *
+ * Returns: (transfer none): a new, floating, `GVariant`
+ */
+GVariant *
+gtk_paper_size_to_gvariant (GtkPaperSize *paper_size)
+{
+  const char *name;
+  const char *ppd_name;
+  const char *display_name;
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+
+  name = gtk_paper_size_get_name (paper_size);
+  ppd_name = gtk_paper_size_get_ppd_name (paper_size);
+  display_name = gtk_paper_size_get_display_name (paper_size);
+
+  if (ppd_name != NULL)
+    g_variant_builder_add (&builder, "{sv}", "PPDName", g_variant_new_string (ppd_name));
+  else
+    g_variant_builder_add (&builder, "{sv}", "Name", g_variant_new_string (name));
+
+  if (display_name != NULL)
+    g_variant_builder_add (&builder, "{sv}", "DisplayName", g_variant_new_string (display_name));
+
+  g_variant_builder_add (&builder, "{sv}", "Width", g_variant_new_double (gtk_paper_size_get_width (paper_size, GTK_UNIT_MM)));
+  g_variant_builder_add (&builder, "{sv}", "Height", g_variant_new_double (gtk_paper_size_get_height (paper_size, GTK_UNIT_MM)));
+
+  return g_variant_builder_end (&builder);
+}
+
+/**
+ * gtk_paper_size_new_from_gvariant:
+ * @variant: an a{sv} `GVariant`
+ *
+ * Deserialize a paper size from a `GVariant`.
+ *
+ * The `GVariant must be in the format produced by
+ * [method@Gtk.PaperSize.to_gvariant].
+ *
+ * Returns: (transfer full): a new `GtkPaperSize` object
+ */
+GtkPaperSize *
+gtk_paper_size_new_from_gvariant (GVariant *variant)
+{
+  GtkPaperSize *paper_size;
+  const char *name;
+  const char *ppd_name;
+  const char *display_name;
+  double width, height;
+
+  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
+
+  if (!g_variant_lookup (variant, "Width", "d", &width) ||
+      !g_variant_lookup (variant, "Height", "d", &height))
+    return NULL;
+
+  if (!g_variant_lookup (variant, "Name", "&s", &name))
+    name = NULL;
+
+  if (!g_variant_lookup (variant, "PPDName", "&s", &ppd_name))
+    ppd_name = NULL;
+
+  if (!g_variant_lookup (variant, "DisplayName", "&s", &display_name))
+    display_name = name;
+
+  if (ppd_name != NULL)
+    paper_size = gtk_paper_size_new_from_ppd (ppd_name,
+                                              display_name,
+                                              _gtk_print_convert_from_mm (width, GTK_UNIT_POINTS),
+                                              _gtk_print_convert_from_mm (height, GTK_UNIT_POINTS));
+  else if (name != NULL)
+    paper_size = gtk_paper_size_new_custom (name, display_name,
+                                            width, height, GTK_UNIT_MM);
+  else
+    paper_size = NULL;
+
+  return paper_size;
+}
diff --git a/gtk/print/gtkprintcontext.c b/gtk/print/gtkprintcontext.c
new file mode 100644 (file)
index 0000000..1141062
--- /dev/null
@@ -0,0 +1,616 @@
+/* GTK - The GIMP Toolkit
+ * gtkprintcontext.c: Print Context
+ * 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 "gtkprintoperation-private.h"
+
+
+/**
+ * GtkPrintContext:
+ *
+ * A `GtkPrintContext` encapsulates context information that is required when
+ * drawing pages for printing.
+ *
+ * This includes the cairo context and important parameters like page size
+ * and resolution. It also lets you easily create [class@Pango.Layout] and
+ * [class@Pango.Context] objects that match the font metrics of the cairo surface.
+ *
+ * `GtkPrintContext` objects get passed to the
+ * [signal@Gtk.PrintOperation::begin-print],
+ * [signal@Gtk.PrintOperation::end-print],
+ * [signal@Gtk.PrintOperation::request-page-setup] and
+ * [signal@Gtk.PrintOperation::draw-page] signals on the
+ * [class@Gtk.PrintOperation] object.
+ *
+ * ## Using GtkPrintContext in a ::draw-page callback
+ *
+ * ```c
+ * static void
+ * draw_page (GtkPrintOperation *operation,
+ *            GtkPrintContext   *context,
+ *            int                page_nr)
+ * {
+ *   cairo_t *cr;
+ *   PangoLayout *layout;
+ *   PangoFontDescription *desc;
+ *
+ *   cr = gtk_print_context_get_cairo_context (context);
+ *
+ *   // Draw a red rectangle, as wide as the paper (inside the margins)
+ *   cairo_set_source_rgb (cr, 1.0, 0, 0);
+ *   cairo_rectangle (cr, 0, 0, gtk_print_context_get_width (context), 50);
+ *
+ *   cairo_fill (cr);
+ *
+ *   // Draw some lines
+ *   cairo_move_to (cr, 20, 10);
+ *   cairo_line_to (cr, 40, 20);
+ *   cairo_arc (cr, 60, 60, 20, 0, M_PI);
+ *   cairo_line_to (cr, 80, 20);
+ *
+ *   cairo_set_source_rgb (cr, 0, 0, 0);
+ *   cairo_set_line_width (cr, 5);
+ *   cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ *   cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ *
+ *   cairo_stroke (cr);
+ *
+ *   // Draw some text
+ *   layout = gtk_print_context_create_pango_layout (context);
+ *   pango_layout_set_text (layout, "Hello World! Printing is easy", -1);
+ *   desc = pango_font_description_from_string ("sans 28");
+ *   pango_layout_set_font_description (layout, desc);
+ *   pango_font_description_free (desc);
+ *
+ *   cairo_move_to (cr, 30, 20);
+ *   pango_cairo_layout_path (cr, layout);
+ *
+ *   // Font Outline
+ *   cairo_set_source_rgb (cr, 0.93, 1.0, 0.47);
+ *   cairo_set_line_width (cr, 0.5);
+ *   cairo_stroke_preserve (cr);
+ *
+ *   // Font Fill
+ *   cairo_set_source_rgb (cr, 0, 0.0, 1.0);
+ *   cairo_fill (cr);
+ *
+ *   g_object_unref (layout);
+ * }
+ * ```
+ */
+
+
+typedef struct _GtkPrintContextClass GtkPrintContextClass;
+
+#define GTK_IS_PRINT_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_CONTEXT))
+#define GTK_PRINT_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
+#define GTK_PRINT_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_CONTEXT, GtkPrintContextClass))
+
+#define MM_PER_INCH 25.4
+#define POINTS_PER_INCH 72
+
+struct _GtkPrintContext
+{
+  GObject parent_instance;
+
+  GtkPrintOperation *op;
+  cairo_t *cr;
+  GtkPageSetup *page_setup;
+
+  double surface_dpi_x;
+  double surface_dpi_y;
+  
+  double pixels_per_unit_x;
+  double pixels_per_unit_y;
+
+  gboolean has_hard_margins;
+  double hard_margin_top;
+  double hard_margin_bottom;
+  double hard_margin_left;
+  double hard_margin_right;
+
+};
+
+struct _GtkPrintContextClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkPrintContext, gtk_print_context, G_TYPE_OBJECT)
+
+static void
+gtk_print_context_finalize (GObject *object)
+{
+  GtkPrintContext *context = GTK_PRINT_CONTEXT (object);
+
+  if (context->page_setup)
+    g_object_unref (context->page_setup);
+
+  if (context->cr)
+    cairo_destroy (context->cr);
+  
+  G_OBJECT_CLASS (gtk_print_context_parent_class)->finalize (object);
+}
+
+static void
+gtk_print_context_init (GtkPrintContext *context)
+{
+}
+
+static void
+gtk_print_context_class_init (GtkPrintContextClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->finalize = gtk_print_context_finalize;
+}
+
+
+GtkPrintContext *
+_gtk_print_context_new (GtkPrintOperation *op)
+{
+  GtkPrintContext *context;
+
+  context = g_object_new (GTK_TYPE_PRINT_CONTEXT, NULL);
+
+  context->op = op;
+  context->cr = NULL;
+  context->has_hard_margins = FALSE;
+  
+  return context;
+}
+
+static PangoFontMap *
+_gtk_print_context_get_fontmap (GtkPrintContext *context)
+{
+  return pango_cairo_font_map_get_default ();
+}
+
+/**
+ * gtk_print_context_set_cairo_context:
+ * @context: a `GtkPrintContext`
+ * @cr: the cairo context
+ * @dpi_x: the horizontal resolution to use with @cr
+ * @dpi_y: the vertical resolution to use with @cr
+ *
+ * Sets a new cairo context on a print context.
+ *
+ * This function is intended to be used when implementing
+ * an internal print preview, it is not needed for printing,
+ * since GTK itself creates a suitable cairo context in that
+ * case.
+ */
+void
+gtk_print_context_set_cairo_context (GtkPrintContext *context,
+                                    cairo_t         *cr,
+                                    double           dpi_x,
+                                    double           dpi_y)
+{
+  if (context->cr)
+    cairo_destroy (context->cr);
+
+  context->cr = cairo_reference (cr);
+  context->surface_dpi_x = dpi_x;
+  context->surface_dpi_y = dpi_y;
+
+  switch (context->op->priv->unit)
+    {
+    default:
+    case GTK_UNIT_NONE:
+      /* Do nothing, this is the cairo default unit */
+      context->pixels_per_unit_x = 1.0;
+      context->pixels_per_unit_y = 1.0;
+      break;
+    case GTK_UNIT_POINTS:
+      context->pixels_per_unit_x = dpi_x / POINTS_PER_INCH;
+      context->pixels_per_unit_y = dpi_y / POINTS_PER_INCH;
+      break;
+    case GTK_UNIT_INCH:
+      context->pixels_per_unit_x = dpi_x;
+      context->pixels_per_unit_y = dpi_y;
+      break;
+    case GTK_UNIT_MM:
+      context->pixels_per_unit_x = dpi_x / MM_PER_INCH;
+      context->pixels_per_unit_y = dpi_y / MM_PER_INCH;
+      break;
+    }
+  cairo_scale (context->cr,
+              context->pixels_per_unit_x,
+              context->pixels_per_unit_y);
+}
+
+
+void
+_gtk_print_context_rotate_according_to_orientation (GtkPrintContext *context)
+{
+  cairo_t *cr = context->cr;
+  cairo_matrix_t matrix;
+  GtkPaperSize *paper_size;
+  double width, height;
+
+  paper_size = gtk_page_setup_get_paper_size (context->page_setup);
+
+  width = gtk_paper_size_get_width (paper_size, GTK_UNIT_INCH);
+  width = width * context->surface_dpi_x / context->pixels_per_unit_x;
+  height = gtk_paper_size_get_height (paper_size, GTK_UNIT_INCH);
+  height = height * context->surface_dpi_y / context->pixels_per_unit_y;
+  
+  switch (gtk_page_setup_get_orientation (context->page_setup))
+    {
+    default:
+    case GTK_PAGE_ORIENTATION_PORTRAIT:
+      break;
+    case GTK_PAGE_ORIENTATION_LANDSCAPE:
+      cairo_translate (cr, 0, height);
+      cairo_matrix_init (&matrix,
+                        0, -1,
+                        1,  0,
+                        0,  0);
+      cairo_transform (cr, &matrix);
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+      cairo_translate (cr, width, height);
+      cairo_matrix_init (&matrix,
+                        -1,  0,
+                         0, -1,
+                         0,  0);
+      cairo_transform (cr, &matrix);
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+      cairo_translate (cr, width, 0);
+      cairo_matrix_init (&matrix,
+                         0,  1,
+                        -1,  0,
+                         0,  0);
+      cairo_transform (cr, &matrix);
+      break;
+    }
+}
+
+void
+_gtk_print_context_reverse_according_to_orientation (GtkPrintContext *context)
+{
+  cairo_t *cr = context->cr;
+  cairo_matrix_t matrix;
+  double width, height;
+
+  width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
+  width = width * context->surface_dpi_x / context->pixels_per_unit_x;
+  height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
+  height = height * context->surface_dpi_y / context->pixels_per_unit_y;
+
+  switch (gtk_page_setup_get_orientation (context->page_setup))
+    {
+    default:
+    case GTK_PAGE_ORIENTATION_PORTRAIT:
+    case GTK_PAGE_ORIENTATION_LANDSCAPE:
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+      cairo_translate (cr, width, height);
+      cairo_matrix_init (&matrix,
+                        -1,  0,
+                         0, -1,
+                         0,  0);
+      cairo_transform (cr, &matrix);
+      break;
+    }
+}
+
+void
+_gtk_print_context_translate_into_margin (GtkPrintContext *context)
+{
+  double dx, dy;
+
+  g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
+
+  /* We do it this way to also handle GTK_UNIT_NONE */
+  switch (gtk_page_setup_get_orientation (context->page_setup))
+    {
+      default:
+      case GTK_PAGE_ORIENTATION_PORTRAIT:
+        dx = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
+        dy = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
+        break;
+      case GTK_PAGE_ORIENTATION_LANDSCAPE:
+        dx = gtk_page_setup_get_bottom_margin (context->page_setup, GTK_UNIT_INCH);
+        dy = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH);
+        break;
+      case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+        dx = gtk_page_setup_get_right_margin (context->page_setup, GTK_UNIT_INCH);
+        dy = gtk_page_setup_get_bottom_margin (context->page_setup, GTK_UNIT_INCH);
+        break;
+      case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+        dx = gtk_page_setup_get_top_margin (context->page_setup, GTK_UNIT_INCH);
+        dy = gtk_page_setup_get_right_margin (context->page_setup, GTK_UNIT_INCH);
+        break;
+    }
+
+  cairo_translate (context->cr,
+                   dx * context->surface_dpi_x / context->pixels_per_unit_x,
+                   dy * context->surface_dpi_y / context->pixels_per_unit_y);
+}
+
+void
+_gtk_print_context_set_page_setup (GtkPrintContext *context,
+                                  GtkPageSetup    *page_setup)
+{
+  g_return_if_fail (GTK_IS_PRINT_CONTEXT (context));
+  g_return_if_fail (page_setup == NULL ||
+                   GTK_IS_PAGE_SETUP (page_setup));
+
+  if (page_setup != NULL)
+    g_object_ref (page_setup);
+
+  if (context->page_setup != NULL)
+    g_object_unref (context->page_setup);
+
+  context->page_setup = page_setup;
+}
+
+/**
+ * gtk_print_context_get_cairo_context:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the cairo context that is associated with the
+ * `GtkPrintContext`.
+ *
+ * Returns: (transfer none): the cairo context of @context
+ */
+cairo_t *
+gtk_print_context_get_cairo_context (GtkPrintContext *context)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
+
+  return context->cr;
+}
+
+/**
+ * gtk_print_context_get_page_setup:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the `GtkPageSetup` that determines the page
+ * dimensions of the `GtkPrintContext`.
+ *
+ * Returns: (transfer none): the page setup of @context
+ */
+GtkPageSetup *
+gtk_print_context_get_page_setup (GtkPrintContext *context)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
+
+  return context->page_setup;
+}
+
+/**
+ * gtk_print_context_get_width:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the width of the `GtkPrintContext`, in pixels.
+ *
+ * Returns: the width of @context
+ */
+double
+gtk_print_context_get_width (GtkPrintContext *context)
+{
+  GtkPrintOperationPrivate *priv;
+  double width;
+
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
+
+  priv = context->op->priv;
+
+  if (priv->use_full_page)
+    width = gtk_page_setup_get_paper_width (context->page_setup, GTK_UNIT_INCH);
+  else
+    width = gtk_page_setup_get_page_width (context->page_setup, GTK_UNIT_INCH);
+
+  /* Really dpi_x? What about landscape? what does dpi_x mean in that case? */
+  return width * context->surface_dpi_x / context->pixels_per_unit_x;
+}
+
+/**
+ * gtk_print_context_get_height:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the height of the `GtkPrintContext`, in pixels.
+ *
+ * Returns: the height of @context
+ */
+double
+gtk_print_context_get_height (GtkPrintContext *context)
+{
+  GtkPrintOperationPrivate *priv;
+  double height;
+
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
+
+  priv = context->op->priv;
+
+  if (priv->use_full_page)
+    height = gtk_page_setup_get_paper_height (context->page_setup, GTK_UNIT_INCH);
+  else
+    height = gtk_page_setup_get_page_height (context->page_setup, GTK_UNIT_INCH);
+
+  /* Really dpi_y? What about landscape? what does dpi_y mean in that case? */
+  return height * context->surface_dpi_y / context->pixels_per_unit_y;
+}
+
+/**
+ * gtk_print_context_get_dpi_x:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the horizontal resolution of the `GtkPrintContext`,
+ * in dots per inch.
+ *
+ * Returns: the horizontal resolution of @context
+ */
+double
+gtk_print_context_get_dpi_x (GtkPrintContext *context)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
+
+  return context->surface_dpi_x;
+}
+
+/**
+ * gtk_print_context_get_dpi_y:
+ * @context: a `GtkPrintContext`
+ *
+ * Obtains the vertical resolution of the `GtkPrintContext`,
+ * in dots per inch.
+ *
+ * Returns: the vertical resolution of @context
+ */
+double
+gtk_print_context_get_dpi_y (GtkPrintContext *context)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), 0);
+
+  return context->surface_dpi_y;
+}
+
+/**
+ * gtk_print_context_get_hard_margins:
+ * @context: a `GtkPrintContext`
+ * @top: (out): top hardware printer margin
+ * @bottom: (out): bottom hardware printer margin
+ * @left: (out): left hardware printer margin
+ * @right: (out): right hardware printer margin
+ *
+ * Obtains the hardware printer margins of the `GtkPrintContext`,
+ * in units.
+ *
+ * Returns: %TRUE if the hard margins were retrieved
+ */
+gboolean
+gtk_print_context_get_hard_margins (GtkPrintContext *context,
+                                   double          *top,
+                                   double          *bottom,
+                                   double          *left,
+                                   double          *right)
+{
+  if (context->has_hard_margins)
+    {
+      *top    = context->hard_margin_top / context->pixels_per_unit_y;
+      *bottom = context->hard_margin_bottom / context->pixels_per_unit_y;
+      *left   = context->hard_margin_left / context->pixels_per_unit_x;
+      *right  = context->hard_margin_right / context->pixels_per_unit_x;
+    }
+
+  return context->has_hard_margins;
+}
+
+/**
+ * gtk_print_context_set_hard_margins:
+ * @context: a `GtkPrintContext`
+ * @top: top hardware printer margin
+ * @bottom: bottom hardware printer margin
+ * @left: left hardware printer margin
+ * @right: right hardware printer margin
+ *
+ * Sets the hard margins in pixels.
+ */
+void
+_gtk_print_context_set_hard_margins (GtkPrintContext *context,
+                                    double           top,
+                                    double           bottom,
+                                    double           left,
+                                    double           right)
+{
+  context->hard_margin_top    = top;
+  context->hard_margin_bottom = bottom;
+  context->hard_margin_left   = left;
+  context->hard_margin_right  = right;
+  context->has_hard_margins   = TRUE;
+}
+
+/**
+ * gtk_print_context_get_pango_fontmap:
+ * @context: a `GtkPrintContext`
+ *
+ * Returns a `PangoFontMap` that is suitable for use
+ * with the `GtkPrintContext`.
+ *
+ * Returns: (transfer none): the font map of @context
+ */
+PangoFontMap *
+gtk_print_context_get_pango_fontmap (GtkPrintContext *context)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
+
+  return _gtk_print_context_get_fontmap (context);
+}
+
+/**
+ * gtk_print_context_create_pango_context:
+ * @context: a `GtkPrintContext`
+ *
+ * Creates a new `PangoContext` that can be used with the
+ * `GtkPrintContext`.
+ *
+ * Returns: (transfer full): a new Pango context for @context
+ */
+PangoContext *
+gtk_print_context_create_pango_context (GtkPrintContext *context)
+{
+  PangoContext *pango_context;
+  cairo_font_options_t *options;
+
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
+  
+  pango_context = pango_font_map_create_context (_gtk_print_context_get_fontmap (context));
+
+  options = cairo_font_options_create ();
+  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
+  pango_cairo_context_set_font_options (pango_context, options);
+  cairo_font_options_destroy (options);
+  
+  /* We use the unit-scaled resolution, as we still want 
+   * fonts given in points to work 
+   */
+  pango_cairo_context_set_resolution (pango_context,
+                                     context->surface_dpi_y / context->pixels_per_unit_y);
+  return pango_context;
+}
+
+/**
+ * gtk_print_context_create_pango_layout:
+ * @context: a `GtkPrintContext`
+ *
+ * Creates a new `PangoLayout` that is suitable for use
+ * with the `GtkPrintContext`.
+ *
+ * Returns: (transfer full): a new Pango layout for @context
+ */
+PangoLayout *
+gtk_print_context_create_pango_layout (GtkPrintContext *context)
+{
+  PangoContext *pango_context;
+  PangoLayout *layout;
+
+  g_return_val_if_fail (GTK_IS_PRINT_CONTEXT (context), NULL);
+
+  pango_context = gtk_print_context_create_pango_context (context);
+  layout = pango_layout_new (pango_context);
+
+  pango_cairo_update_context (context->cr, pango_context);
+  g_object_unref (pango_context);
+
+  return layout;
+}
diff --git a/gtk/print/gtkprintoperation.c b/gtk/print/gtkprintoperation.c
new file mode 100644 (file)
index 0000000..c4b0fab
--- /dev/null
@@ -0,0 +1,3282 @@
+/* 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/>.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include <cairo-pdf.h>
+
+#include "gtkprintoperation-private.h"
+#include "gtkmarshalers.h"
+#include "gdk/gdkmarshalers.h"
+#include <glib/gi18n-lib.h>
+#include "gtkprivate.h"
+#include "deprecated/gtkmessagedialog.h"
+#include "gtkwindowgroup.h"
+#include "gtktypebuiltins.h"
+
+/**
+ * GtkPrintOperation:
+ *
+ * `GtkPrintOperation` is the high-level, portable printing API.
+ *
+ * It looks a bit different than other GTK dialogs such as the
+ * `GtkFileChooser`, since some platforms don’t expose enough
+ * infrastructure to implement a good print dialog. On such
+ * platforms, `GtkPrintOperation` uses the native print dialog.
+ * On platforms which do not provide a native print dialog, GTK
+ * uses its own, see [class@Gtk.PrintUnixDialog].
+ *
+ * The typical way to use the high-level printing API is to create
+ * a `GtkPrintOperation` object with [ctor@Gtk.PrintOperation.new]
+ * when the user selects to print. Then you set some properties on it,
+ * e.g. the page size, any [class@Gtk.PrintSettings] from previous print
+ * operations, the number of pages, the current page, etc.
+ *
+ * Then you start the print operation by calling [method@Gtk.PrintOperation.run].
+ * It will then show a dialog, let the user select a printer and options.
+ * When the user finished the dialog, various signals will be emitted on
+ * the `GtkPrintOperation`, the main one being
+ * [signal@Gtk.PrintOperation::draw-page], which you are supposed to handle
+ * and render the page on the provided [class@Gtk.PrintContext] using Cairo.
+ *
+ * # The high-level printing API
+ *
+ * ```c
+ * static GtkPrintSettings *settings = NULL;
+ *
+ * static void
+ * do_print (void)
+ * {
+ *   GtkPrintOperation *print;
+ *   GtkPrintOperationResult res;
+ *
+ *   print = gtk_print_operation_new ();
+ *
+ *   if (settings != NULL)
+ *     gtk_print_operation_set_print_settings (print, settings);
+ *
+ *   g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), NULL);
+ *   g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), NULL);
+ *
+ *   res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ *                                  GTK_WINDOW (main_window), NULL);
+ *
+ *   if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
+ *     {
+ *       if (settings != NULL)
+ *         g_object_unref (settings);
+ *       settings = g_object_ref (gtk_print_operation_get_print_settings (print));
+ *     }
+ *
+ *   g_object_unref (print);
+ * }
+ * ```
+ *
+ * By default `GtkPrintOperation` uses an external application to do
+ * print preview. To implement a custom print preview, an application
+ * must connect to the preview signal. The functions
+ * [method@Gtk.PrintOperationPreview.render_page],
+ * [method@Gtk.PrintOperationPreview.end_preview] and
+ * [method@Gtk.PrintOperationPreview.is_selected]
+ * are useful when implementing a print preview.
+ */
+
+#define SHOW_PROGRESS_TIME 1200
+
+
+enum
+{
+  DONE,
+  BEGIN_PRINT,
+  PAGINATE,
+  REQUEST_PAGE_SETUP,
+  DRAW_PAGE,
+  END_PRINT,
+  STATUS_CHANGED,
+  CREATE_CUSTOM_WIDGET,
+  CUSTOM_WIDGET_APPLY,
+  PREVIEW,
+  UPDATE_CUSTOM_WIDGET,
+  LAST_SIGNAL
+};
+
+enum 
+{
+  PROP_0,
+  PROP_DEFAULT_PAGE_SETUP,
+  PROP_PRINT_SETTINGS,
+  PROP_JOB_NAME,
+  PROP_N_PAGES,
+  PROP_CURRENT_PAGE,
+  PROP_USE_FULL_PAGE,
+  PROP_TRACK_PRINT_STATUS,
+  PROP_UNIT,
+  PROP_SHOW_PROGRESS,
+  PROP_ALLOW_ASYNC,
+  PROP_EXPORT_FILENAME,
+  PROP_STATUS,
+  PROP_STATUS_STRING,
+  PROP_CUSTOM_TAB_LABEL,
+  PROP_EMBED_PAGE_SETUP,
+  PROP_HAS_SELECTION,
+  PROP_SUPPORT_SELECTION,
+  PROP_N_PAGES_TO_PRINT
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+static int job_nr = 0;
+typedef struct _PrintPagesData PrintPagesData;
+
+static void          preview_iface_init      (GtkPrintOperationPreviewIface *iface);
+static GtkPageSetup *create_page_setup       (GtkPrintOperation             *op);
+static void          common_render_page      (GtkPrintOperation             *op,
+                                             int                            page_nr);
+static void          increment_page_sequence (PrintPagesData *data);
+static void          prepare_data            (PrintPagesData *data);
+static void          clamp_page_ranges       (PrintPagesData *data);
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkPrintOperation, gtk_print_operation, G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (GtkPrintOperation)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_PRINT_OPERATION_PREVIEW,
+                                               preview_iface_init))
+
+/**
+ * gtk_print_error_quark:
+ *
+ * Registers an error quark for `GtkPrintOperation` if necessary.
+ * 
+ * Returns: The error quark used for `GtkPrintOperation` errors.
+ **/
+GQuark     
+gtk_print_error_quark (void)
+{
+  static GQuark quark = 0;
+  if (quark == 0)
+    quark = g_quark_from_static_string ("gtk-print-error-quark");
+  return quark;
+}
+     
+static void
+gtk_print_operation_finalize (GObject *object)
+{
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  if (priv->free_platform_data &&
+      priv->platform_data)
+    {
+      priv->free_platform_data (priv->platform_data);
+      priv->free_platform_data = NULL;
+    }
+
+  if (priv->default_page_setup)
+    g_object_unref (priv->default_page_setup);
+  
+  if (priv->print_settings)
+    g_object_unref (priv->print_settings);
+  
+  if (priv->print_context)
+    g_object_unref (priv->print_context);
+
+  g_free (priv->export_filename);
+  g_free (priv->job_name);
+  g_free (priv->custom_tab_label);
+  g_free (priv->status_string);
+
+  if (priv->print_pages_idle_id > 0)
+    g_source_remove (priv->print_pages_idle_id);
+
+  if (priv->show_progress_timeout_id > 0)
+    g_source_remove (priv->show_progress_timeout_id);
+
+  if (priv->error)
+    g_error_free (priv->error);
+  
+  G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object);
+}
+
+static void
+gtk_print_operation_init (GtkPrintOperation *operation)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (operation);
+  const char *appname;
+
+  priv->status = GTK_PRINT_STATUS_INITIAL;
+  priv->status_string = g_strdup ("");
+  priv->default_page_setup = NULL;
+  priv->print_settings = NULL;
+  priv->nr_of_pages = -1;
+  priv->nr_of_pages_to_print = -1;
+  priv->page_position = -1;
+  priv->current_page = -1;
+  priv->use_full_page = FALSE;
+  priv->show_progress = FALSE;
+  priv->export_filename = NULL;
+  priv->track_print_status = FALSE;
+  priv->is_sync = FALSE;
+  priv->support_selection = FALSE;
+  priv->has_selection = FALSE;
+  priv->embed_page_setup = FALSE;
+
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
+
+  priv->rloop = NULL;
+  priv->unit = GTK_UNIT_NONE;
+
+  appname = g_get_application_name ();
+  if (appname == NULL)
+    appname = "";
+  /* translators: this string is the default job title for print
+   * jobs. %s gets replaced by the application name, %d gets replaced
+   * by the job number.
+   */
+  priv->job_name = g_strdup_printf (_("%s job #%d"), appname, ++job_nr);
+  operation->priv = priv;
+}
+
+static void
+preview_iface_render_page (GtkPrintOperationPreview *preview,
+                          int                       page_nr)
+{
+
+  GtkPrintOperation *op;
+
+  op = GTK_PRINT_OPERATION (preview);
+  common_render_page (op, page_nr);
+}
+
+static void
+preview_iface_end_preview (GtkPrintOperationPreview *preview)
+{
+  GtkPrintOperation *op;
+  GtkPrintOperationResult result;
+  
+  op = GTK_PRINT_OPERATION (preview);
+
+  g_signal_emit (op, signals[END_PRINT], 0, op->priv->print_context);
+
+  if (op->priv->rloop)
+    g_main_loop_quit (op->priv->rloop);
+  
+  if (op->priv->end_run)
+    op->priv->end_run (op, op->priv->is_sync, TRUE);
+  
+  _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
+
+  if (op->priv->error)
+    result = GTK_PRINT_OPERATION_RESULT_ERROR;
+  else if (op->priv->cancelled)
+    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  else
+    result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+  g_signal_emit (op, signals[DONE], 0, result);
+}
+
+static gboolean
+preview_iface_is_selected (GtkPrintOperationPreview *preview,
+                          int                       page_nr)
+{
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  int i;
+
+  switch (priv->print_pages)
+    {
+    case GTK_PRINT_PAGES_SELECTION:
+    case GTK_PRINT_PAGES_ALL:
+      return (page_nr >= 0) && (page_nr < priv->nr_of_pages);
+    case GTK_PRINT_PAGES_CURRENT:
+      return page_nr == priv->current_page;
+    case GTK_PRINT_PAGES_RANGES:
+      for (i = 0; i < priv->num_page_ranges; i++)
+       {
+         if (page_nr >= priv->page_ranges[i].start &&
+             (page_nr <= priv->page_ranges[i].end || priv->page_ranges[i].end == -1))
+           return TRUE;
+       }
+      return FALSE;
+    default:
+      return FALSE;
+    }
+}
+
+static void
+preview_iface_init (GtkPrintOperationPreviewIface *iface)
+{
+  iface->render_page = preview_iface_render_page;
+  iface->end_preview = preview_iface_end_preview;
+  iface->is_selected = preview_iface_is_selected;
+}
+
+static void
+preview_start_page (GtkPrintOperation *op,
+                   GtkPrintContext   *print_context,
+                   GtkPageSetup      *page_setup)
+{
+  if ((op->priv->manual_number_up < 2) ||
+      (op->priv->page_position % op->priv->manual_number_up == 0))
+    g_signal_emit_by_name (op, "got-page-size", print_context, page_setup);
+}
+
+static void
+preview_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
+preview_end_run (GtkPrintOperation *op,
+                gboolean           wait,
+                gboolean           cancelled)
+{
+  g_free (op->priv->page_ranges);
+  op->priv->page_ranges = NULL;
+}
+
+
+static void
+gtk_print_operation_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
+  
+  switch (prop_id)
+    {
+    case PROP_DEFAULT_PAGE_SETUP:
+      gtk_print_operation_set_default_page_setup (op, g_value_get_object (value));
+      break;
+    case PROP_PRINT_SETTINGS:
+      gtk_print_operation_set_print_settings (op, g_value_get_object (value));
+      break;
+    case PROP_JOB_NAME:
+      gtk_print_operation_set_job_name (op, g_value_get_string (value));
+      break;
+    case PROP_N_PAGES:
+      gtk_print_operation_set_n_pages (op, g_value_get_int (value));
+      break;
+    case PROP_CURRENT_PAGE:
+      gtk_print_operation_set_current_page (op, g_value_get_int (value));
+      break;
+    case PROP_USE_FULL_PAGE:
+      gtk_print_operation_set_use_full_page (op, g_value_get_boolean (value));
+      break;
+    case PROP_TRACK_PRINT_STATUS:
+      gtk_print_operation_set_track_print_status (op, g_value_get_boolean (value));
+      break;
+    case PROP_UNIT:
+      gtk_print_operation_set_unit (op, g_value_get_enum (value));
+      break;
+    case PROP_ALLOW_ASYNC:
+      gtk_print_operation_set_allow_async (op, g_value_get_boolean (value));
+      break;
+    case PROP_SHOW_PROGRESS:
+      gtk_print_operation_set_show_progress (op, g_value_get_boolean (value));
+      break;
+    case PROP_EXPORT_FILENAME:
+      gtk_print_operation_set_export_filename (op, g_value_get_string (value));
+      break;
+    case PROP_CUSTOM_TAB_LABEL:
+      gtk_print_operation_set_custom_tab_label (op, g_value_get_string (value));
+      break;
+    case PROP_EMBED_PAGE_SETUP:
+      gtk_print_operation_set_embed_page_setup (op, g_value_get_boolean (value));
+      break;
+    case PROP_HAS_SELECTION:
+      gtk_print_operation_set_has_selection (op, g_value_get_boolean (value));
+      break;
+    case PROP_SUPPORT_SELECTION:
+      gtk_print_operation_set_support_selection (op, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_print_operation_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  switch (prop_id)
+    {
+    case PROP_DEFAULT_PAGE_SETUP:
+      g_value_set_object (value, priv->default_page_setup);
+      break;
+    case PROP_PRINT_SETTINGS:
+      g_value_set_object (value, priv->print_settings);
+      break;
+    case PROP_JOB_NAME:
+      g_value_set_string (value, priv->job_name);
+      break;
+    case PROP_N_PAGES:
+      g_value_set_int (value, priv->nr_of_pages);
+      break;
+    case PROP_CURRENT_PAGE:
+      g_value_set_int (value, priv->current_page);
+      break;      
+    case PROP_USE_FULL_PAGE:
+      g_value_set_boolean (value, priv->use_full_page);
+      break;
+    case PROP_TRACK_PRINT_STATUS:
+      g_value_set_boolean (value, priv->track_print_status);
+      break;
+    case PROP_UNIT:
+      g_value_set_enum (value, priv->unit);
+      break;
+    case PROP_ALLOW_ASYNC:
+      g_value_set_boolean (value, priv->allow_async);
+      break;
+    case PROP_SHOW_PROGRESS:
+      g_value_set_boolean (value, priv->show_progress);
+      break;
+    case PROP_EXPORT_FILENAME:
+      g_value_set_string (value, priv->export_filename);
+      break;
+    case PROP_STATUS:
+      g_value_set_enum (value, priv->status);
+      break;
+    case PROP_STATUS_STRING:
+      g_value_set_string (value, priv->status_string);
+      break;
+    case PROP_CUSTOM_TAB_LABEL:
+      g_value_set_string (value, priv->custom_tab_label);
+      break;
+    case PROP_EMBED_PAGE_SETUP:
+      g_value_set_boolean (value, priv->embed_page_setup);
+      break;
+    case PROP_HAS_SELECTION:
+      g_value_set_boolean (value, priv->has_selection);
+      break;
+    case PROP_SUPPORT_SELECTION:
+      g_value_set_boolean (value, priv->support_selection);
+      break;
+    case PROP_N_PAGES_TO_PRINT:
+      g_value_set_int (value, priv->nr_of_pages_to_print);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+struct _PrintPagesData
+{
+  GtkPrintOperation *op;
+  int uncollated_copies;
+  int collated_copies;
+  int uncollated, collated, total;
+
+  int range, num_ranges;
+  GtkPageRange *ranges;
+  GtkPageRange one_range;
+
+  int page;
+  int sheet;
+  int first_position, last_position;
+  int first_sheet;
+  int num_of_sheets;
+  int *pages;
+
+  GtkWidget *progress;
+  gboolean initialized;
+  gboolean is_preview;
+  gboolean done;
+};
+
+typedef struct
+{
+  GtkPrintOperationPreview *preview;
+  GtkPrintContext *print_context;
+  GtkWindow *parent;
+  cairo_surface_t *surface;
+  char *filename;
+  gboolean wait;
+  PrintPagesData *pages_data;
+} PreviewOp;
+
+static void
+preview_print_idle_done (gpointer data)
+{
+  GtkPrintOperation *op;
+  PreviewOp *pop = (PreviewOp *) data;
+
+  op = GTK_PRINT_OPERATION (pop->preview);
+
+  cairo_surface_finish (pop->surface);
+
+  if (op->priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED)
+    {
+      cairo_surface_destroy (pop->surface);
+    }
+  else
+    {
+      /* Surface is destroyed in launch_preview */
+      _gtk_print_operation_platform_backend_launch_preview (op,
+                                                           pop->surface,
+                                                           pop->parent,
+                                                           pop->filename);
+    }
+
+  g_free (pop->filename);
+
+  gtk_print_operation_preview_end_preview (pop->preview);
+
+  g_object_unref (pop->pages_data->op);
+  g_free (pop->pages_data->pages);
+  g_free (pop->pages_data);
+
+  g_object_unref (op);
+  g_free (pop);
+}
+
+static gboolean
+preview_print_idle (gpointer data)
+{
+  PreviewOp *pop = (PreviewOp *) data;
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (pop->preview);
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  gboolean done = FALSE;
+
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
+    {
+      if (priv->cancelled)
+       {
+         done = TRUE;
+          _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+       }
+      else if (!pop->pages_data->initialized)
+        {
+          pop->pages_data->initialized = TRUE;
+          prepare_data (pop->pages_data);
+        }
+      else
+        {
+          increment_page_sequence (pop->pages_data);
+
+          if (!pop->pages_data->done)
+            gtk_print_operation_preview_render_page (pop->preview, pop->pages_data->page);
+          else
+            done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
+        }
+    }
+
+  return !done;
+}
+
+static void
+preview_got_page_size (GtkPrintOperationPreview *preview, 
+                      GtkPrintContext          *context,
+                      GtkPageSetup             *page_setup,
+                      PreviewOp                *pop)
+{
+  GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
+  cairo_t *cr;
+
+  _gtk_print_operation_platform_backend_resize_preview_surface (op, page_setup, pop->surface);
+
+  cr = gtk_print_context_get_cairo_context (pop->print_context);
+  _gtk_print_operation_platform_backend_preview_start_page (op, pop->surface, cr);
+
+}
+
+static void
+preview_ready (GtkPrintOperationPreview *preview,
+               GtkPrintContext          *context,
+              PreviewOp                *pop)
+{
+  guint id;
+
+  pop->print_context = context;
+
+  g_object_ref (preview);
+      
+  id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
+                        preview_print_idle,
+                        pop,
+                        preview_print_idle_done);
+  gdk_source_set_static_name_by_id (id, "[gtk] preview_print_idle");
+}
+
+
+static gboolean
+gtk_print_operation_preview_handler (GtkPrintOperation        *op,
+                                     GtkPrintOperationPreview *preview, 
+                                    GtkPrintContext          *context,
+                                    GtkWindow                *parent)
+{
+  double dpi_x, dpi_y;
+  PreviewOp *pop;
+  GtkPageSetup *page_setup;
+  cairo_t *cr;
+
+  pop = g_new0 (PreviewOp, 1);
+  pop->filename = NULL;
+  pop->preview = preview;
+  pop->parent = parent;
+  pop->pages_data = g_new0 (PrintPagesData, 1);
+  pop->pages_data->op = g_object_ref (GTK_PRINT_OPERATION (preview));
+  pop->pages_data->is_preview = TRUE;
+
+  page_setup = gtk_print_context_get_page_setup (context);
+
+  pop->surface =
+    _gtk_print_operation_platform_backend_create_preview_surface (op,
+                                                                 page_setup,
+                                                                 &dpi_x, &dpi_y,
+                                                                 &pop->filename);
+
+  if (pop->surface == NULL)
+    {
+      g_free (pop);
+      return FALSE;
+    }
+
+  cr = cairo_create (pop->surface);
+  gtk_print_context_set_cairo_context (op->priv->print_context, cr,
+                                      dpi_x, dpi_y);
+  cairo_destroy (cr);
+
+  g_signal_connect (preview, "ready", (GCallback) preview_ready, pop);
+  g_signal_connect (preview, "got-page-size", (GCallback) preview_got_page_size, pop);
+  
+  return TRUE;
+}
+
+static GtkWidget *
+gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
+{
+  return NULL;
+}
+
+static gboolean
+gtk_print_operation_paginate (GtkPrintOperation *operation,
+                              GtkPrintContext   *context)
+{
+  /* assume the number of pages is already set and pagination is not needed */
+  return TRUE;
+}
+
+static void
+gtk_print_operation_done (GtkPrintOperation       *operation,
+                          GtkPrintOperationResult  result)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (operation);
+
+  if (priv->print_context)
+    {
+      g_object_unref (priv->print_context);
+      priv->print_context = NULL;
+    } 
+}
+
+static gboolean
+custom_widget_accumulator (GSignalInvocationHint *ihint,
+                          GValue                *return_accu,
+                          const GValue          *handler_return,
+                          gpointer               dummy)
+{
+  gboolean continue_emission;
+  GtkWidget *widget;
+  
+  widget = g_value_get_object (handler_return);
+  if (widget != NULL)
+    g_value_set_object (return_accu, widget);
+  continue_emission = (widget == NULL);
+  
+  return continue_emission;
+}
+
+static gboolean
+paginate_accumulator (GSignalInvocationHint *ihint,
+                      GValue                *return_accu,
+                      const GValue          *handler_return,
+                      gpointer               dummy)
+{
+  *return_accu = *handler_return;
+
+  /* Stop signal emission on first invocation, so if it's a callback then
+   * the default handler won't run. */
+  return FALSE;
+}
+
+static void
+gtk_print_operation_class_init (GtkPrintOperationClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->set_property = gtk_print_operation_set_property;
+  gobject_class->get_property = gtk_print_operation_get_property;
+  gobject_class->finalize = gtk_print_operation_finalize;
+  class->preview = gtk_print_operation_preview_handler; 
+  class->create_custom_widget = gtk_print_operation_create_custom_widget;
+  class->paginate = gtk_print_operation_paginate;
+  class->done = gtk_print_operation_done;
+
+  /**
+   * GtkPrintOperation::done:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @result: the result of the print operation
+   *
+   * Emitted when the print operation run has finished doing
+   * everything required for printing.
+   *
+   * @result gives you information about what happened during the run.
+   * If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
+   * [method@Gtk.PrintOperation.get_error] for more information.
+   *
+   * If you enabled print status tracking then
+   * [method@Gtk.PrintOperation.is_finished] may still return %FALSE
+   * after the ::done signal was emitted.
+   */
+  signals[DONE] =
+    g_signal_new (I_("done"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, done),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_OPERATION_RESULT);
+
+  /**
+   * GtkPrintOperation::begin-print:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @context: the `GtkPrintContext` for the current operation
+   *
+   * Emitted after the user has finished changing print settings
+   * in the dialog, before the actual rendering starts.
+   *
+   * A typical use for ::begin-print is to use the parameters from the
+   * [class@Gtk.PrintContext] and paginate the document accordingly,
+   * and then set the number of pages with
+   * [method@Gtk.PrintOperation.set_n_pages].
+   */
+  signals[BEGIN_PRINT] =
+    g_signal_new (I_("begin-print"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, begin_print),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
+
+   /**
+   * GtkPrintOperation::paginate:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @context: the `GtkPrintContext` for the current operation
+   *
+   * Emitted after the ::begin-print signal, but before the actual rendering
+   * starts.
+   *
+   * It keeps getting emitted until a connected signal handler returns %TRUE.
+   *
+   * The ::paginate signal is intended to be used for paginating a document
+   * in small chunks, to avoid blocking the user interface for a long
+   * time. The signal handler should update the number of pages using
+   * [method@Gtk.PrintOperation.set_n_pages], and return %TRUE if the document
+   * has been completely paginated.
+   *
+   * If you don't need to do pagination in chunks, you can simply do
+   * it all in the ::begin-print handler, and set the number of pages
+   * from there.
+   *
+   * Returns: %TRUE if pagination is complete
+   */
+  signals[PAGINATE] =
+    g_signal_new (I_("paginate"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkPrintOperationClass, paginate),
+                  paginate_accumulator, NULL,
+                  _gdk_marshal_BOOLEAN__OBJECT,
+                  G_TYPE_BOOLEAN, 1, GTK_TYPE_PRINT_CONTEXT);
+  g_signal_set_va_marshaller (signals[PAGINATE],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gdk_marshal_BOOLEAN__OBJECTv);
+
+  /**
+   * GtkPrintOperation::request-page-setup:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @context: the `GtkPrintContext` for the current operation
+   * @page_nr: the number of the currently printed page (0-based)
+   * @setup: the `GtkPageSetup`
+   *
+   * Emitted once for every page that is printed.
+   *
+   * This gives the application a chance to modify the page setup.
+   * Any changes done to @setup will be in force only for printing
+   * this page.
+   */
+  signals[REQUEST_PAGE_SETUP] =
+    g_signal_new (I_("request-page-setup"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkPrintOperationClass, request_page_setup),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_INT_OBJECT,
+                  G_TYPE_NONE, 3,
+                  GTK_TYPE_PRINT_CONTEXT,
+                  G_TYPE_INT,
+                  GTK_TYPE_PAGE_SETUP);
+  g_signal_set_va_marshaller (signals[REQUEST_PAGE_SETUP],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_VOID__OBJECT_INT_OBJECTv);
+
+  /**
+   * GtkPrintOperation::draw-page:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @context: the `GtkPrintContext` for the current operation
+   * @page_nr: the number of the currently printed page (0-based)
+   *
+   * Emitted for every page that is printed.
+   *
+   * The signal handler must render the @page_nr's page onto the cairo
+   * context obtained from @context using
+   * [method@Gtk.PrintContext.get_cairo_context].
+   *
+   * ```c
+   * static void
+   * draw_page (GtkPrintOperation *operation,
+   *            GtkPrintContext   *context,
+   *            int                page_nr,
+   *            gpointer           user_data)
+   * {
+   *   cairo_t *cr;
+   *   PangoLayout *layout;
+   *   double width, text_height;
+   *   int layout_height;
+   *   PangoFontDescription *desc;
+   *   
+   *   cr = gtk_print_context_get_cairo_context (context);
+   *   width = gtk_print_context_get_width (context);
+   *   
+   *   cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
+   *   
+   *   cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
+   *   cairo_fill (cr);
+   *   
+   *   layout = gtk_print_context_create_pango_layout (context);
+   *   
+   *   desc = pango_font_description_from_string ("sans 14");
+   *   pango_layout_set_font_description (layout, desc);
+   *   pango_font_description_free (desc);
+   *   
+   *   pango_layout_set_text (layout, "some text", -1);
+   *   pango_layout_set_width (layout, width * PANGO_SCALE);
+   *   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+   *                         
+   *   pango_layout_get_size (layout, NULL, &layout_height);
+   *   text_height = (double)layout_height / PANGO_SCALE;
+   *   
+   *   cairo_move_to (cr, width / 2,  (HEADER_HEIGHT - text_height) / 2);
+   *   pango_cairo_show_layout (cr, layout);
+   *   
+   *   g_object_unref (layout);
+   * }
+   * ```
+   *
+   * Use [method@Gtk.PrintOperation.set_use_full_page] and
+   * [method@Gtk.PrintOperation.set_unit] before starting the print
+   * operation to set up the transformation of the cairo context
+   * according to your needs.
+   */
+  signals[DRAW_PAGE] =
+    g_signal_new (I_("draw-page"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, draw_page),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_INT,
+                 G_TYPE_NONE, 2,
+                 GTK_TYPE_PRINT_CONTEXT,
+                 G_TYPE_INT);
+  g_signal_set_va_marshaller (signals[DRAW_PAGE],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_VOID__OBJECT_INTv);
+
+  /**
+   * GtkPrintOperation::end-print:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @context: the `GtkPrintContext` for the current operation
+   *
+   * Emitted after all pages have been rendered.
+   *
+   * A handler for this signal can clean up any resources that have
+   * been allocated in the [signal@Gtk.PrintOperation::begin-print] handler.
+   */
+  signals[END_PRINT] =
+    g_signal_new (I_("end-print"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, end_print),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
+
+  /**
+   * GtkPrintOperation::status-changed:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   *
+   * Emitted at between the various phases of the print operation.
+   *
+   * See [enum@Gtk.PrintStatus] for the phases that are being discriminated.
+   * Use [method@Gtk.PrintOperation.get_status] to find out the current
+   * status.
+   */
+  signals[STATUS_CHANGED] =
+    g_signal_new (I_("status-changed"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 0);
+
+
+  /**
+   * GtkPrintOperation::create-custom-widget:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   *
+   * Emitted when displaying the print dialog.
+   *
+   * If you return a widget in a handler for this signal it will be
+   * added to a custom tab in the print dialog. You typically return a
+   * container widget with multiple widgets in it.
+   *
+   * The print dialog owns the returned widget, and its lifetime is not
+   * controlled by the application. However, the widget is guaranteed
+   * to stay around until the [signal@Gtk.PrintOperation::custom-widget-apply]
+   * signal is emitted on the operation. Then you can read out any
+   * information you need from the widgets.
+   *
+   * Returns: (nullable) (transfer none): A custom widget that gets embedded in
+   *   the print dialog
+   */
+  signals[CREATE_CUSTOM_WIDGET] =
+    g_signal_new (I_("create-custom-widget"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
+                 custom_widget_accumulator, NULL,
+                 _gtk_marshal_OBJECT__VOID,
+                 G_TYPE_OBJECT, 0);
+  g_signal_set_va_marshaller (signals[CREATE_CUSTOM_WIDGET],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_OBJECT__VOIDv);
+
+  /**
+   * GtkPrintOperation::update-custom-widget:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @widget: the custom widget added in ::create-custom-widget
+   * @setup: actual page setup
+   * @settings: actual print settings
+   *
+   * Emitted after change of selected printer.
+   *
+   * The actual page setup and print settings are passed to the custom
+   * widget, which can actualize itself according to this change.
+   */
+  signals[UPDATE_CUSTOM_WIDGET] =
+    g_signal_new (I_("update-custom-widget"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, update_custom_widget),
+                 NULL, NULL,
+                 _gtk_marshal_VOID__OBJECT_OBJECT_OBJECT,
+                 G_TYPE_NONE, 3, GTK_TYPE_WIDGET, GTK_TYPE_PAGE_SETUP, GTK_TYPE_PRINT_SETTINGS);
+  g_signal_set_va_marshaller (signals[UPDATE_CUSTOM_WIDGET],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_VOID__OBJECT_OBJECT_OBJECTv);
+
+  /**
+   * GtkPrintOperation::custom-widget-apply:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @widget: the custom widget added in ::create-custom-widget
+   *
+   * Emitted right before ::begin-print if you added
+   * a custom widget in the ::create-custom-widget handler.
+   *
+   * When you get this signal you should read the information from the
+   * custom widgets, as the widgets are not guaranteed to be around at a
+   * later time.
+   */
+  signals[CUSTOM_WIDGET_APPLY] =
+    g_signal_new (I_("custom-widget-apply"),
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
+                 NULL, NULL,
+                 NULL,
+                 G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+   /**
+   * GtkPrintOperation::preview:
+   * @operation: the `GtkPrintOperation` on which the signal was emitted
+   * @preview: the `GtkPrintOperationPreview` for the current operation
+   * @context: the `GtkPrintContext` that will be used
+   * @parent: (nullable): the `GtkWindow` to use as window parent
+   *
+   * Gets emitted when a preview is requested from the native dialog.
+   *
+   * The default handler for this signal uses an external viewer
+   * application to preview.
+   *
+   * To implement a custom print preview, an application must return
+   * %TRUE from its handler for this signal. In order to use the
+   * provided @context for the preview implementation, it must be
+   * given a suitable cairo context with
+   * [method@Gtk.PrintContext.set_cairo_context].
+   *
+   * The custom preview implementation can use
+   * [method@Gtk.PrintOperationPreview.is_selected] and
+   * [method@Gtk.PrintOperationPreview.render_page] to find pages which
+   * are selected for print and render them. The preview must be
+   * finished by calling [method@Gtk.PrintOperationPreview.end_preview]
+   * (typically in response to the user clicking a close button).
+   *
+   * Returns: %TRUE if the listener wants to take over control of the preview
+   */
+  signals[PREVIEW] =
+    g_signal_new (I_("preview"),
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkPrintOperationClass, preview),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
+                 G_TYPE_BOOLEAN, 3,
+                 GTK_TYPE_PRINT_OPERATION_PREVIEW,
+                 GTK_TYPE_PRINT_CONTEXT,
+                 GTK_TYPE_WINDOW);
+  g_signal_set_va_marshaller (signals[PREVIEW],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECTv);
+
+  /**
+   * GtkPrintOperation:default-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_default_page_setup org.gtk.Property.set=gtk_print_operation_set_default_page_setup)
+   *
+   * The `GtkPageSetup` used by default.
+   *
+   * This page setup will be used by [method@Gtk.PrintOperation.run],
+   * but it can be overridden on a per-page basis by connecting
+   * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_DEFAULT_PAGE_SETUP,
+                                  g_param_spec_object ("default-page-setup", NULL, NULL,
+                                                       GTK_TYPE_PAGE_SETUP,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintOperation:print-settings: (attributes org.gtk.Property.get=gtk_print_operation_get_print_settings org.gtk.Property.set=gtk_print_operation_set_print_settings)
+   *
+   * The `GtkPrintSettings` used for initializing the dialog.
+   *
+   * Setting this property is typically used to re-establish
+   * print settings from a previous print operation, see
+   * [method@Gtk.PrintOperation.run].
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_PRINT_SETTINGS,
+                                  g_param_spec_object ("print-settings", NULL, NULL,
+                                                       GTK_TYPE_PRINT_SETTINGS,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintOperation:job-name: (attributes org.gtk.Property.set=gtk_print_operation_set_job_name)
+   *
+   * A string used to identify the job (e.g. in monitoring
+   * applications like eggcups).
+   *
+   * If you don't set a job name, GTK picks a default one
+   * by numbering successive print jobs.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_JOB_NAME,
+                                  g_param_spec_string ("job-name", NULL, NULL,
+                                                       "",
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintOperation:n-pages: (attributes org.gtk.Property.set=gtk_print_operation_set_n_pages)
+   *
+   * The number of pages in the document.
+   *
+   * This must be set to a positive number before the rendering
+   * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
+   * signal handler.
+   *
+   * Note that the page numbers passed to the
+   * [signal@Gtk.PrintOperation::request-page-setup] and
+   * [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
+   * if the user chooses to print all pages, the last ::draw-page signal
+   * will be for page @n_pages - 1.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_N_PAGES,
+                                  g_param_spec_int ("n-pages", NULL, NULL,
+                                                    -1,
+                                                    G_MAXINT,
+                                                    -1,
+                                                    GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:current-page: (attributes org.gtk.Property.set=gtk_print_operation_set_current_page)
+   *
+   * The current page in the document.
+   *
+   * If this is set before [method@Gtk.PrintOperation.run],
+   * the user will be able to select to print only the current page.
+   *
+   * Note that this only makes sense for pre-paginated documents.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_CURRENT_PAGE,
+                                  g_param_spec_int ("current-page", NULL, NULL,
+                                                    -1,
+                                                    G_MAXINT,
+                                                    -1,
+                                                    GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:use-full-page: (attributes org.gtk.Property.set=gtk_print_operation_set_use_full_page)
+   *
+   * If %TRUE, the transformation for the cairo context obtained
+   * from `GtkPrintContext` puts the origin at the top left corner
+   * of the page.
+   *
+   * This may not be the top left corner of the sheet, depending on
+   * page orientation and the number of pages per sheet. Otherwise,
+   * the origin is at the top left corner of the imageable area (i.e.
+   * inside the margins).
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_USE_FULL_PAGE,
+                                  g_param_spec_boolean ("use-full-page", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:track-print-status: (attributes org.gtk.Property.set=gtk_print_operation_set_track_print_status)
+   *
+   * If %TRUE, the print operation 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.
+   * However, this is often implemented using polling, and should
+   * not be enabled unless needed.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_TRACK_PRINT_STATUS,
+                                  g_param_spec_boolean ("track-print-status", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:unit: (attributes org.gtk.Property.set=gtk_print_operation_set_unit)
+   *
+   * The transformation for the cairo context obtained from
+   * `GtkPrintContext` is set up in such a way that distances
+   * are measured in units of @unit.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_UNIT,
+                                  g_param_spec_enum ("unit", NULL, NULL,
+                                                     GTK_TYPE_UNIT,
+                                                     GTK_UNIT_NONE,
+                                                     GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:show-progress: (attributes org.gtk.Property.set=gtk_print_operation_set_show_progress)
+   *
+   * Determines whether to show a progress dialog during the
+   * print operation.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_SHOW_PROGRESS,
+                                  g_param_spec_boolean ("show-progress", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:allow-async: (attributes org.gtk.Property.set=gtk_print_operation_set_allow_async)
+   *
+   * Determines whether the print operation may run asynchronously or not.
+   *
+   * Some systems don't support asynchronous printing, but those that do
+   * will return %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS as the status, and
+   * emit the [signal@Gtk.PrintOperation::done] signal when the operation
+   * is actually done.
+   *
+   * The Windows port does not support asynchronous operation at all (this
+   * is unlikely to change). On other platforms, all actions except for
+   * %GTK_PRINT_OPERATION_ACTION_EXPORT support asynchronous operation.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_ALLOW_ASYNC,
+                                  g_param_spec_boolean ("allow-async", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:export-filename: (attributes org.gtk.Property.set=gtk_print_operation_set_export_filename)
+   *
+   * The name of a file to generate instead of showing the print dialog.
+   *
+   * Currently, PDF is the only supported format.
+   *
+   * The intended use of this property is for implementing
+   * “Export to PDF” actions.
+   *
+   * “Print to PDF” support is independent of this and is done
+   * by letting the user pick the “Print to PDF” item from the
+   * list of printers in the print dialog.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_EXPORT_FILENAME,
+                                  g_param_spec_string ("export-filename", NULL, NULL,
+                                                       NULL,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintOperation:status: (attributes org.gtk.Property.get=gtk_print_operation_get_status)
+   *
+   * The status of the print operation.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_STATUS,
+                                  g_param_spec_enum ("status", NULL, NULL,
+                                                     GTK_TYPE_PRINT_STATUS,
+                                                     GTK_PRINT_STATUS_INITIAL,
+                                                     GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:status-string: (attributes org.gtk.Property.get=gtk_print_operation_get_status_string)
+   *
+   * A string representation of the status of the print operation.
+   *
+   * The string is translated and suitable for displaying the print
+   * status e.g. in a `GtkStatusbar`.
+   *
+   * See the [property@Gtk.PrintOperation:status] property for a status
+   * value that is suitable for programmatic use.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_STATUS_STRING,
+                                  g_param_spec_string ("status-string", NULL, NULL,
+                                                       "",
+                                                       GTK_PARAM_READABLE));
+  
+
+  /**
+   * GtkPrintOperation:custom-tab-label: (attributes org.gtk.Property.set=gtk_print_operation_set_custom_tab_label)
+   *
+   * Used as the label of the tab containing custom widgets.
+   *
+   * Note that this property may be ignored on some platforms.
+   *
+   * If this is %NULL, GTK uses a default label.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_CUSTOM_TAB_LABEL,
+                                  g_param_spec_string ("custom-tab-label", NULL, NULL,
+                                                       NULL,
+                                                       GTK_PARAM_READWRITE));
+
+  /**
+   * GtkPrintOperation:support-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_support_selection org.gtk.Property.set=gtk_print_operation_set_support_selection)
+   *
+   * If %TRUE, the print operation will support print of selection.
+   *
+   * This allows the print dialog to show a "Selection" button.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_SUPPORT_SELECTION,
+                                  g_param_spec_boolean ("support-selection", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:has-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_has_selection org.gtk.Property.set=gtk_print_operation_set_has_selection)
+   *
+   * Determines whether there is a selection in your application.
+   *
+   * This can allow your application to print the selection.
+   * This is typically used to make a "Selection" button sensitive.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_HAS_SELECTION,
+                                  g_param_spec_boolean ("has-selection", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+
+  /**
+   * GtkPrintOperation:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_embed_page_setup org.gtk.Property.set=gtk_print_operation_set_embed_page_setup)
+   *
+   * If %TRUE, page size combo box and orientation combo box
+   * are embedded into page setup page.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_EMBED_PAGE_SETUP,
+                                  g_param_spec_boolean ("embed-page-setup", NULL, NULL,
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  /**
+   * GtkPrintOperation:n-pages-to-print: (attributes org.gtk.Property.get=gtk_print_operation_get_n_pages_to_print)
+   *
+   * The number of pages that will be printed.
+   *
+   * Note that this value is set during print preparation phase
+   * (%GTK_PRINT_STATUS_PREPARING), so this value should never be
+   * get before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
+   * You can connect to the [signal@Gtk.PrintOperation::status-changed] signal
+   * and call [method@Gtk.PrintOperation.get_n_pages_to_print] when
+   * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
+   *
+   * This is typically used to track the progress of print operation.
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_N_PAGES_TO_PRINT,
+                                  g_param_spec_int ("n-pages-to-print", NULL, NULL,
+                                                    -1,
+                                                    G_MAXINT,
+                                                    -1,
+                                                    GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
+}
+
+/**
+ * gtk_print_operation_new:
+ *
+ * Creates a new `GtkPrintOperation`.
+ *
+ * Returns: a new `GtkPrintOperation`
+ */
+GtkPrintOperation *
+gtk_print_operation_new (void)
+{
+  GtkPrintOperation *print_operation;
+
+  print_operation = g_object_new (GTK_TYPE_PRINT_OPERATION, NULL);
+  
+  return print_operation;
+}
+
+/**
+ * gtk_print_operation_set_default_page_setup: (attributes org.gtk.Method.set_property=default-page-setup)
+ * @op: a `GtkPrintOperation`
+ * @default_page_setup: (nullable): a `GtkPageSetup`
+ *
+ * Makes @default_page_setup the default page setup for @op.
+ *
+ * This page setup will be used by [method@Gtk.PrintOperation.run],
+ * but it can be overridden on a per-page basis by connecting
+ * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
+ **/
+void
+gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
+                                           GtkPageSetup      *default_page_setup)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_if_fail (default_page_setup == NULL ||
+                    GTK_IS_PAGE_SETUP (default_page_setup));
+
+  if (default_page_setup != priv->default_page_setup)
+    {
+      if (default_page_setup)
+       g_object_ref (default_page_setup);
+      
+      if (priv->default_page_setup)
+       g_object_unref (priv->default_page_setup);
+      
+      priv->default_page_setup = default_page_setup;
+     
+      g_object_notify (G_OBJECT (op), "default-page-setup");
+    }
+}
+
+/**
+ * gtk_print_operation_get_default_page_setup: (attributes org.gtk.Method.get_property=default-page-setup)
+ * @op: a `GtkPrintOperation`
+ *
+ * Returns the default page setup.
+ *
+ * Returns: (transfer none): the default page setup
+ */
+GtkPageSetup *
+gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
+
+  return op->priv->default_page_setup;
+}
+
+
+/**
+ * gtk_print_operation_set_print_settings: (attributes org.gtk.Method.set_property=print-settings)
+ * @op: a `GtkPrintOperation`
+ * @print_settings: (nullable): `GtkPrintSettings`
+ *
+ * Sets the print settings for @op.
+ *
+ * This is typically used to re-establish print settings
+ * from a previous print operation, see [method@Gtk.PrintOperation.run].
+ */
+void
+gtk_print_operation_set_print_settings (GtkPrintOperation *op,
+                                       GtkPrintSettings  *print_settings)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_if_fail (print_settings == NULL || 
+                    GTK_IS_PRINT_SETTINGS (print_settings));
+
+  if (print_settings != priv->print_settings)
+    {
+      if (print_settings)
+        g_object_ref (print_settings);
+
+      if (priv->print_settings)
+        g_object_unref (priv->print_settings);
+  
+      priv->print_settings = print_settings;
+
+      g_object_notify (G_OBJECT (op), "print-settings");
+    }
+}
+
+/**
+ * gtk_print_operation_get_print_settings: (attributes org.gtk.Method.get_property=print-settings)
+ * @op: a `GtkPrintOperation`
+ *
+ * Returns the current print settings.
+ *
+ * Note that the return value is %NULL until either
+ * [method@Gtk.PrintOperation.set_print_settings] or
+ * [method@Gtk.PrintOperation.run] have been called.
+ *
+ * Returns: (transfer none) (nullable): the current print settings of @op.
+ **/
+GtkPrintSettings *
+gtk_print_operation_get_print_settings (GtkPrintOperation *op)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
+
+  return op->priv->print_settings;
+}
+
+/**
+ * gtk_print_operation_set_job_name: (attributes org.gtk.Method.set_property=job-name)
+ * @op: a `GtkPrintOperation`
+ * @job_name: a string that identifies the print job
+ *
+ * Sets the name of the print job.
+ *
+ * The name is used to identify the job (e.g. in monitoring
+ * applications like eggcups).
+ *
+ * If you don’t set a job name, GTK picks a default one by
+ * numbering successive print jobs.
+ */
+void
+gtk_print_operation_set_job_name (GtkPrintOperation *op,
+                                 const char        *job_name)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_if_fail (job_name != NULL);
+
+  if (g_strcmp0 (priv->job_name, job_name) == 0)
+    return;
+
+  g_free (priv->job_name);
+  priv->job_name = g_strdup (job_name);
+
+  g_object_notify (G_OBJECT (op), "job-name");
+}
+
+/**
+ * gtk_print_operation_set_n_pages: (attributes org.gtk.Method.set_property=n-pages)
+ * @op: a `GtkPrintOperation`
+ * @n_pages: the number of pages
+ *
+ * Sets the number of pages in the document.
+ *
+ * This must be set to a positive number before the rendering
+ * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
+ * signal handler.
+ *
+ * Note that the page numbers passed to the
+ * [signal@Gtk.PrintOperation::request-page-setup]
+ * and [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
+ * if the user chooses to print all pages, the last ::draw-page signal
+ * will be for page @n_pages - 1.
+ */
+void
+gtk_print_operation_set_n_pages (GtkPrintOperation *op,
+                                int                n_pages)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_if_fail (n_pages > 0);
+  g_return_if_fail (priv->current_page == -1 || 
+                    priv->current_page < n_pages);
+
+  if (priv->nr_of_pages != n_pages)
+    {
+      priv->nr_of_pages = n_pages;
+
+      g_object_notify (G_OBJECT (op), "n-pages");
+    }
+}
+
+/**
+ * gtk_print_operation_set_current_page: (attributes org.gtk.Method.set_property=current-page)
+ * @op: a `GtkPrintOperation`
+ * @current_page: the current page, 0-based
+ *
+ * Sets the current page.
+ *
+ * If this is called before [method@Gtk.PrintOperation.run],
+ * the user will be able to select to print only the current page.
+ *
+ * Note that this only makes sense for pre-paginated documents.
+ */
+void
+gtk_print_operation_set_current_page (GtkPrintOperation *op,
+                                     int                current_page)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_if_fail (current_page >= 0);
+  g_return_if_fail (priv->nr_of_pages == -1 || 
+                   current_page < priv->nr_of_pages);
+
+  if (priv->current_page != current_page)
+    {
+      priv->current_page = current_page;
+
+      g_object_notify (G_OBJECT (op), "current-page");
+    }
+}
+
+/**
+ * gtk_print_operation_set_use_full_page: (attributes org.gtk.Method.set_property=use-full-page)
+ * @op: a `GtkPrintOperation`
+ * @full_page: %TRUE to set up the `GtkPrintContext` for the full page
+ *
+ * If @full_page is %TRUE, the transformation for the cairo context
+ * obtained from `GtkPrintContext` puts the origin at the top left
+ * corner of the page.
+ *
+ * This may not be the top left corner of the sheet, depending on page
+ * orientation and the number of pages per sheet). Otherwise, the origin
+ * is at the top left corner of the imageable area (i.e. inside the margins).
+ */
+void
+gtk_print_operation_set_use_full_page (GtkPrintOperation *op,
+                                      gboolean           full_page)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  full_page = full_page != FALSE;
+
+  if (priv->use_full_page != full_page)
+    {
+      priv->use_full_page = full_page;
+   
+      g_object_notify (G_OBJECT (op), "use-full-page");
+    }
+}
+
+/**
+ * gtk_print_operation_set_unit: (attributes org.gtk.Method.set_property=unit)
+ * @op: a `GtkPrintOperation`
+ * @unit: the unit to use
+ *
+ * Sets up the transformation for the cairo context obtained from
+ * `GtkPrintContext` in such a way that distances are measured in
+ * units of @unit.
+ */
+void
+gtk_print_operation_set_unit (GtkPrintOperation *op,
+                             GtkUnit            unit)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  if (priv->unit != unit)
+    {
+      priv->unit = unit;
+
+      g_object_notify (G_OBJECT (op), "unit");
+    }
+}
+
+/**
+ * gtk_print_operation_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
+ * @op: a `GtkPrintOperation`
+ * @track_status: %TRUE to track status after printing
+ *
+ * If track_status is %TRUE, the print operation 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_operation_set_track_print_status (GtkPrintOperation  *op,
+                                           gboolean            track_status)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  if (priv->track_print_status != track_status)
+    {
+      priv->track_print_status = track_status;
+
+      g_object_notify (G_OBJECT (op), "track-print-status");
+    }
+}
+
+void
+_gtk_print_operation_set_status (GtkPrintOperation *op,
+                                GtkPrintStatus     status,
+                                const char        *string)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  static const char *status_strs[] = {
+    NC_("print operation status", "Initial state"),
+    NC_("print operation status", "Preparing to print"),
+    NC_("print operation status", "Generating data"),
+    NC_("print operation status", "Sending data"),
+    NC_("print operation status", "Waiting"),
+    NC_("print operation status", "Blocking on issue"),
+    NC_("print operation status", "Printing"),
+    NC_("print operation status", "Finished"),
+    NC_("print operation status", "Finished with error")
+  };
+
+  if (status > GTK_PRINT_STATUS_FINISHED_ABORTED)
+    status = GTK_PRINT_STATUS_FINISHED_ABORTED;
+
+  if (string == NULL)
+    string = g_dpgettext2 (GETTEXT_PACKAGE, "print operation status", status_strs[status]);
+  
+  if (priv->status == status &&
+      strcmp (string, priv->status_string) == 0)
+    return;
+  
+  g_free (priv->status_string);
+  priv->status_string = g_strdup (string);
+  priv->status = status;
+
+  g_object_notify (G_OBJECT (op), "status");
+  g_object_notify (G_OBJECT (op), "status-string");
+
+  g_signal_emit (op, signals[STATUS_CHANGED], 0);
+}
+
+
+/**
+ * gtk_print_operation_get_status: (attributes org.gtk.Method.get_property=status)
+ * @op: a `GtkPrintOperation`
+ *
+ * Returns the status of the print operation.
+ *
+ * Also see [method@Gtk.PrintOperation.get_status_string].
+ *
+ * Returns: the status of the print operation
+ */
+GtkPrintStatus
+gtk_print_operation_get_status (GtkPrintOperation *op)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
+                        GTK_PRINT_STATUS_FINISHED_ABORTED);
+
+  return op->priv->status;
+}
+
+/**
+ * gtk_print_operation_get_status_string: (attributes org.gtk.Method.get_property=status-string)
+ * @op: a `GtkPrintOperation`
+ *
+ * Returns a string representation of the status of the
+ * print operation.
+ *
+ * The string is translated and suitable for displaying
+ * the print status e.g. in a `GtkStatusbar`.
+ *
+ * Use [method@Gtk.PrintOperation.get_status] to obtain
+ * a status value that is suitable for programmatic use.
+ *
+ * Returns: a string representation of the status
+ *    of the print operation
+ */
+const char *
+gtk_print_operation_get_status_string (GtkPrintOperation *op)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
+
+  return op->priv->status_string;
+}
+
+/**
+ * gtk_print_operation_is_finished:
+ * @op: a `GtkPrintOperation`
+ *
+ * A convenience function to find out if the print operation
+ * is finished.
+ *
+ * a print operation is finished if its status is either
+ * %GTK_PRINT_STATUS_FINISHED or %GTK_PRINT_STATUS_FINISHED_ABORTED.
+ *
+ * Note: when you enable print status tracking the print operation
+ * can be in a non-finished state even after done has been called, as
+ * the operation status then tracks the print job status on the printer.
+ *
+ * Returns: %TRUE, if the print operation is finished.
+ */
+gboolean
+gtk_print_operation_is_finished (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE);
+
+  return
+    priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED ||
+    priv->status == GTK_PRINT_STATUS_FINISHED;
+}
+
+/**
+ * gtk_print_operation_set_show_progress: (attributes org.gtk.Method.set_property=show-progress)
+ * @op: a `GtkPrintOperation`
+ * @show_progress: %TRUE to show a progress dialog
+ *
+ * If @show_progress is %TRUE, the print operation will show
+ * a progress dialog during the print operation.
+ */
+void
+gtk_print_operation_set_show_progress (GtkPrintOperation  *op,
+                                      gboolean            show_progress)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  show_progress = show_progress != FALSE;
+
+  if (priv->show_progress != show_progress)
+    {
+      priv->show_progress = show_progress;
+
+      g_object_notify (G_OBJECT (op), "show-progress");
+    }
+}
+
+/**
+ * gtk_print_operation_set_allow_async: (attributes org.gtk.Method.set_property=allow-async)
+ * @op: a `GtkPrintOperation`
+ * @allow_async: %TRUE to allow asynchronous operation
+ *
+ * Sets whether gtk_print_operation_run() may return
+ * before the print operation is completed.
+ *
+ * Note that some platforms may not allow asynchronous
+ * operation.
+ */
+void
+gtk_print_operation_set_allow_async (GtkPrintOperation  *op,
+                                    gboolean            allow_async)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  allow_async = allow_async != FALSE;
+
+  if (priv->allow_async != allow_async)
+    {
+      priv->allow_async = allow_async;
+
+      g_object_notify (G_OBJECT (op), "allow-async");
+    }
+}
+
+
+/**
+ * gtk_print_operation_set_custom_tab_label: (attributes org.gtk.Method.set_property=custom-tab-label)
+ * @op: a `GtkPrintOperation`
+ * @label: (nullable): the label to use, or %NULL to use the default label
+ *
+ * Sets the label for the tab holding custom widgets.
+ */
+void
+gtk_print_operation_set_custom_tab_label (GtkPrintOperation  *op,
+                                         const char         *label)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  g_free (priv->custom_tab_label);
+  priv->custom_tab_label = g_strdup (label);
+
+  g_object_notify (G_OBJECT (op), "custom-tab-label");
+}
+
+
+/**
+ * gtk_print_operation_set_export_filename: (attributes org.gtk.Method.set_property=export-filename)
+ * @op: a `GtkPrintOperation`
+ * @filename: (type filename): the filename for the exported file
+ *
+ * Sets up the `GtkPrintOperation` to generate a file instead
+ * of showing the print dialog.
+ *
+ * The intended use of this function is for implementing
+ * “Export to PDF” actions. Currently, PDF is the only supported
+ * format.
+ *
+ * “Print to PDF” support is independent of this and is done
+ * by letting the user pick the “Print to PDF” item from the list
+ * of printers in the print dialog.
+ */
+void
+gtk_print_operation_set_export_filename (GtkPrintOperation *op,
+                                        const char        *filename)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  g_free (priv->export_filename);
+  priv->export_filename = g_strdup (filename);
+
+  g_object_notify (G_OBJECT (op), "export-filename");
+}
+
+/* Creates the initial page setup used for printing unless the
+ * app overrides this on a per-page basis using request_page_setup.
+ *
+ * Data is taken from, in order, if existing:
+ *
+ * PrintSettings returned from the print dialog
+ *  (initial dialog values are set from default_page_setup
+ *   if unset in app specified print_settings)
+ * default_page_setup
+ * per-locale default setup
+ */
+static GtkPageSetup *
+create_page_setup (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  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;
+}
+
+static void 
+pdf_start_page (GtkPrintOperation *op,
+               GtkPrintContext   *print_context,
+               GtkPageSetup      *page_setup)
+{
+  cairo_surface_t *surface = op->priv->platform_data;
+  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 void
+pdf_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
+pdf_end_run (GtkPrintOperation *op,
+            gboolean           wait,
+            gboolean           cancelled)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  cairo_surface_t *surface = priv->platform_data;
+
+  cairo_surface_finish (surface);
+  cairo_surface_destroy (surface);
+
+  priv->platform_data = NULL;
+  priv->free_platform_data = NULL;
+}
+
+static GtkPrintOperationResult
+run_pdf (GtkPrintOperation  *op,
+        GtkWindow          *parent,
+        gboolean           *do_print)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  GtkPageSetup *page_setup;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  double width, height;
+  
+  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);
+
+  /* This will be overwritten later by the non-default size, but
+     we need to pass some size: */
+  width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+  height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+  g_object_unref (page_setup);
+  
+  surface = cairo_pdf_surface_create (priv->export_filename,
+                                     width, height);
+  if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+    {
+      g_set_error_literal (&priv->error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_GENERAL,
+                           cairo_status_to_string (cairo_surface_status (surface)));
+      *do_print = FALSE;
+      return GTK_PRINT_OPERATION_RESULT_ERROR;
+    }
+
+  /* this would crash on a nil surface */
+  cairo_surface_set_fallback_resolution (surface, 300, 300);
+
+  priv->platform_data = surface;
+  priv->free_platform_data = (GDestroyNotify) cairo_surface_destroy;
+
+  cr = cairo_create (surface);
+  gtk_print_context_set_cairo_context (op->priv->print_context,
+                                      cr, 72, 72);
+  cairo_destroy (cr);
+
+  
+  priv->print_pages = GTK_PRINT_PAGES_ALL;
+  priv->page_ranges = NULL;
+  priv->num_page_ranges = 0;
+
+  priv->manual_num_copies = 1;
+  priv->manual_collation = FALSE;
+  priv->manual_reverse = FALSE;
+  priv->manual_page_set = GTK_PAGE_SET_ALL;
+  priv->manual_scale = 1.0;
+  priv->manual_orientation = FALSE;
+  priv->manual_number_up = 1;
+  priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+  
+  *do_print = TRUE;
+  
+  priv->start_page = pdf_start_page;
+  priv->end_page = pdf_end_page;
+  priv->end_run = pdf_end_run;
+  
+  return GTK_PRINT_OPERATION_RESULT_APPLY; 
+}
+
+
+static void
+clamp_page_ranges (PrintPagesData *data)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+  int                       num_of_correct_ranges;
+  int                       i;
+
+  num_of_correct_ranges = 0;
+
+  for (i = 0; i < data->num_ranges; i++)
+    if ((data->ranges[i].start >= 0) &&
+        (data->ranges[i].start < priv->nr_of_pages) &&
+        (data->ranges[i].end >= 0) &&
+        (data->ranges[i].end < priv->nr_of_pages))
+      {
+        data->ranges[num_of_correct_ranges] = data->ranges[i];
+        num_of_correct_ranges++;
+      }
+    else if ((data->ranges[i].start >= 0) &&
+             (data->ranges[i].start < priv->nr_of_pages) &&
+             (data->ranges[i].end >= priv->nr_of_pages))
+      {
+        data->ranges[i].end = priv->nr_of_pages - 1;
+        data->ranges[num_of_correct_ranges] = data->ranges[i];
+        num_of_correct_ranges++;
+      }
+    else if ((data->ranges[i].end >= 0) &&
+             (data->ranges[i].end < priv->nr_of_pages) &&
+             (data->ranges[i].start < 0))
+      {
+        data->ranges[i].start = 0;
+        data->ranges[num_of_correct_ranges] = data->ranges[i];
+        num_of_correct_ranges++;
+      }
+
+  data->num_ranges = num_of_correct_ranges;
+}
+
+static void
+increment_page_sequence (PrintPagesData *data)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+  int inc;
+
+  if (data->total == -1)
+    {
+      data->total = 0;
+      return;
+    }
+
+  /* check whether we reached last position */
+  if (priv->page_position == data->last_position &&
+      !(data->collated_copies > 1 && data->collated < (data->collated_copies - 1)))
+    {
+      if (data->uncollated_copies > 1 && data->uncollated < (data->uncollated_copies - 1))
+        {
+          priv->page_position = data->first_position;
+          data->sheet = data->first_sheet;
+          data->uncollated++;
+        }
+      else
+        {
+          data->done = TRUE;
+         return;
+        }
+    }
+  else
+    {
+      if (priv->manual_reverse)
+        inc = -1;
+      else
+        inc = 1;
+
+      /* changing sheet */
+      if (priv->manual_number_up < 2 ||
+          (priv->page_position + 1) % priv->manual_number_up == 0 ||
+          priv->page_position == data->last_position ||
+          priv->page_position == priv->nr_of_pages_to_print - 1)
+        {
+          /* check whether to print the same sheet again */
+          if (data->collated_copies > 1)
+            {
+              if (data->collated < (data->collated_copies - 1))
+                {
+                  data->collated++;
+                  data->total++;
+                  priv->page_position = data->sheet * priv->manual_number_up;
+
+                  if (priv->page_position < 0 ||
+                      priv->page_position >= priv->nr_of_pages_to_print ||
+                      data->sheet < 0 ||
+                      data->sheet >= data->num_of_sheets)
+                   {
+                      data->done = TRUE;
+                     return;
+                   }
+                  else
+                    data->page = data->pages[priv->page_position];
+
+                  return;
+                }
+              else
+                data->collated = 0;
+            }
+
+          if (priv->manual_page_set == GTK_PAGE_SET_ODD ||
+              priv->manual_page_set == GTK_PAGE_SET_EVEN)
+            data->sheet += 2 * inc;
+          else
+            data->sheet += inc;
+
+          priv->page_position = data->sheet * priv->manual_number_up;
+        }
+      else
+        priv->page_position += 1;
+    }
+
+  /* general check */
+  if (priv->page_position < 0 ||
+      priv->page_position >= priv->nr_of_pages_to_print ||
+      data->sheet < 0 ||
+      data->sheet >= data->num_of_sheets)
+    {
+      data->done = TRUE;
+      return;
+    }
+  else
+    data->page = data->pages[priv->page_position];
+
+  data->total++;
+}
+
+static void
+print_pages_idle_done (gpointer user_data)
+{
+  PrintPagesData *data = (PrintPagesData*)user_data;
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+
+  priv->print_pages_idle_id = 0;
+
+  if (priv->show_progress_timeout_id > 0)
+    {
+      g_source_remove (priv->show_progress_timeout_id);
+      priv->show_progress_timeout_id = 0;
+    }
+  if (data->progress)
+    gtk_window_destroy (GTK_WINDOW (data->progress));
+
+  if (priv->rloop && !data->is_preview) 
+    g_main_loop_quit (priv->rloop);
+
+  if (!data->is_preview)
+    {
+      GtkPrintOperationResult result;
+
+      if (priv->error)
+        result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      else if (priv->cancelled)
+        result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+      else
+        result = GTK_PRINT_OPERATION_RESULT_APPLY;
+
+      g_signal_emit (data->op, signals[DONE], 0, result);
+    }
+  
+  g_object_unref (data->op);
+  g_free (data->pages);
+  g_free (data);
+}
+
+static void
+update_progress (PrintPagesData *data)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+  char *text = NULL;
+
+  if (data->progress)
+    {
+      if (priv->status == GTK_PRINT_STATUS_PREPARING)
+       {
+         if (priv->nr_of_pages_to_print > 0)
+           text = g_strdup_printf (_("Preparing %d"), priv->nr_of_pages_to_print);
+         else
+           text = g_strdup (_("Preparing"));
+       }
+      else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
+       text = g_strdup_printf (_("Printing %d"), data->total);
+      
+      if (text)
+       {
+         g_object_set (data->progress, "text", text, NULL);
+         g_free (text);
+       }
+    }
+ }
+
+/**
+ * gtk_print_operation_set_defer_drawing:
+ * @op: a `GtkPrintOperation`
+ *
+ * Sets up the `GtkPrintOperation` to wait for calling of
+ * [method@Gtk.PrintOperation.draw_page_finish from application.
+ *
+ * This can be used for drawing page in another thread.
+ *
+ * This function must be called in the callback of the
+ * [signal@Gtk.PrintOperation::draw-page] signal.
+ */
+void
+gtk_print_operation_set_defer_drawing (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING);
+
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING;
+}
+
+/**
+ * gtk_print_operation_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
+ * @op: a `GtkPrintOperation`
+ * @embed: %TRUE to embed page setup selection in the `GtkPrintUnixDialog`
+ *
+ * Embed page size combo box and orientation combo box into page setup page.
+ *
+ * Selected page setup is stored as default page setup in `GtkPrintOperation`.
+ */
+void
+gtk_print_operation_set_embed_page_setup (GtkPrintOperation  *op,
+                                          gboolean            embed)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  embed = embed != FALSE;
+  if (priv->embed_page_setup != embed)
+    {
+      priv->embed_page_setup = embed;
+      g_object_notify (G_OBJECT (op), "embed-page-setup");
+    }
+}
+
+/**
+ * gtk_print_operation_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
+ * @op: a `GtkPrintOperation`
+ *
+ * Gets whether page setup selection combos are embedded
+ *
+ * Returns: whether page setup selection combos are embedded
+ */
+gboolean
+gtk_print_operation_get_embed_page_setup (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
+
+  return priv->embed_page_setup;
+}
+
+/**
+ * gtk_print_operation_draw_page_finish:
+ * @op: a `GtkPrintOperation`
+ *
+ * Signal that drawing of particular page is complete.
+ *
+ * It is called after completion of page drawing (e.g. drawing
+ * in another thread). If [method@Gtk.PrintOperation.set_defer_drawing]
+ * was called before, then this function has to be called by application.
+ * Otherwise it is called by GTK itself.
+ */
+void
+gtk_print_operation_draw_page_finish (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  GtkPageSetup *page_setup;
+  GtkPrintContext *print_context;
+  cairo_t *cr;
+  
+  print_context = priv->print_context;
+  page_setup = gtk_print_context_get_page_setup (print_context);
+
+  cr = gtk_print_context_get_cairo_context (print_context);
+
+  priv->end_page (op, print_context);
+  
+  cairo_restore (cr);
+
+  g_object_unref (page_setup);
+
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
+}
+
+static void
+common_render_page (GtkPrintOperation *op,
+                   int                page_nr)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  GtkPageSetup *page_setup;
+  GtkPrintContext *print_context;
+  cairo_t *cr;
+
+  print_context = priv->print_context;
+  
+  page_setup = create_page_setup (op);
+  
+  g_signal_emit (op, signals[REQUEST_PAGE_SETUP], 0, 
+                print_context, page_nr, page_setup);
+  
+  _gtk_print_context_set_page_setup (print_context, page_setup);
+  
+  priv->start_page (op, print_context, page_setup);
+  
+  cr = gtk_print_context_get_cairo_context (print_context);
+  
+  cairo_save (cr);
+  
+  if (priv->manual_orientation)
+    _gtk_print_context_rotate_according_to_orientation (print_context);
+  else
+    _gtk_print_context_reverse_according_to_orientation (print_context);
+
+  if (priv->manual_number_up <= 1)
+    {
+      if (!priv->use_full_page)
+        _gtk_print_context_translate_into_margin (print_context);
+      if (priv->manual_scale != 1.0)
+        cairo_scale (cr,
+                     priv->manual_scale,
+                     priv->manual_scale);
+    }
+  else
+    {
+      GtkPageOrientation  orientation;
+      double              paper_width, paper_height;
+      double              page_width, page_height;
+      double              context_width, context_height;
+      double              bottom_margin, top_margin, left_margin, right_margin;
+      double              x_step, y_step;
+      double              x_scale, y_scale, scale;
+      double              horizontal_offset = 0.0, vertical_offset = 0.0;
+      int                 columns, rows, x, y, tmp_length;
+
+      page_setup = gtk_print_context_get_page_setup (print_context);
+      orientation = gtk_page_setup_get_orientation (page_setup);
+
+      top_margin = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_POINTS);
+      bottom_margin = gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_POINTS);
+      left_margin = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_POINTS);
+      right_margin = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_POINTS);
+
+      paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
+      paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
+
+      context_width = gtk_print_context_get_width (print_context);
+      context_height = gtk_print_context_get_height (print_context);
+
+      if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+          orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+        {
+          page_width = paper_width - (left_margin + right_margin);
+          page_height = paper_height - (top_margin + bottom_margin);
+        }
+      else
+        {
+          page_width = paper_width - (top_margin + bottom_margin);
+          page_height = paper_height - (left_margin + right_margin);
+        }
+
+      if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
+          orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
+        cairo_translate (cr, left_margin, top_margin);
+      else
+        cairo_translate (cr, top_margin, left_margin);
+
+      switch (priv->manual_number_up)
+        {
+          default:
+            columns = 1;
+            rows = 1;
+            break;
+          case 2:
+            columns = 2;
+            rows = 1;
+            break;
+          case 4:
+            columns = 2;
+            rows = 2;
+            break;
+          case 6:
+            columns = 3;
+            rows = 2;
+            break;
+          case 9:
+            columns = 3;
+            rows = 3;
+            break;
+          case 16:
+            columns = 4;
+            rows = 4;
+            break;
+        }
+
+      if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
+          orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
+        {
+          tmp_length = columns;
+          columns = rows;
+          rows = tmp_length;
+        }
+
+      switch (priv->manual_number_up_layout)
+        {
+          case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
+            x = priv->page_position % columns;
+            y = (priv->page_position / columns) % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
+            x = priv->page_position % columns;
+            y = rows - 1 - (priv->page_position / columns) % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
+            x = columns - 1 - priv->page_position % columns;
+            y = (priv->page_position / columns) % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
+            x = columns - 1 - priv->page_position % columns;
+            y = rows - 1 - (priv->page_position / columns) % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
+            x = (priv->page_position / rows) % columns;
+            y = priv->page_position % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
+            x = columns - 1 - (priv->page_position / rows) % columns;
+            y = priv->page_position % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
+            x = (priv->page_position / rows) % columns;
+            y = rows - 1 - priv->page_position % rows;
+            break;
+          case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
+            x = columns - 1 - (priv->page_position / rows) % columns;
+            y = rows - 1 - priv->page_position % rows;
+            break;
+          default:
+            g_assert_not_reached();
+            x = 0;
+            y = 0;
+        }
+
+      if (priv->manual_number_up == 4 || priv->manual_number_up == 9 || priv->manual_number_up == 16)
+        {
+          x_scale = page_width / (columns * paper_width);
+          y_scale = page_height / (rows * paper_height);
+
+          scale = x_scale < y_scale ? x_scale : y_scale;
+
+          x_step = paper_width * (x_scale / scale);
+          y_step = paper_height * (y_scale / scale);
+
+          if ((left_margin + right_margin) > 0)
+            {
+              horizontal_offset = left_margin * (x_step - context_width) / (left_margin + right_margin);
+              vertical_offset = top_margin * (y_step - context_height) / (top_margin + bottom_margin);
+            }
+          else
+            {
+              horizontal_offset = (x_step - context_width) / 2.0;
+              vertical_offset = (y_step - context_height) / 2.0;
+            }
+
+          cairo_scale (cr, scale, scale);
+
+          cairo_translate (cr,
+                           x * x_step + horizontal_offset,
+                           y * y_step + vertical_offset);
+
+          if (priv->manual_scale != 1.0)
+            cairo_scale (cr, priv->manual_scale, priv->manual_scale);
+        }
+
+      if (priv->manual_number_up == 2 || priv->manual_number_up == 6)
+        {
+          x_scale = page_height / (columns * paper_width);
+          y_scale = page_width / (rows * paper_height);
+
+          scale = x_scale < y_scale ? x_scale : y_scale;
+
+          horizontal_offset = (paper_width * (x_scale / scale) - paper_width) / 2.0 * columns;
+          vertical_offset = (paper_height * (y_scale / scale) - paper_height) / 2.0 * rows;
+
+          if (!priv->use_full_page)
+            {
+              horizontal_offset -= right_margin;
+              vertical_offset += top_margin;
+            }
+
+          cairo_scale (cr, scale, scale);
+
+          cairo_translate (cr,
+                           y * paper_height + vertical_offset,
+                           (columns - x) * paper_width + horizontal_offset);
+
+          if (priv->manual_scale != 1.0)
+            cairo_scale (cr, priv->manual_scale, priv->manual_scale);
+
+          cairo_rotate (cr, - G_PI / 2);
+        }
+    }
+  
+  priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DRAWING;
+
+  g_signal_emit (op, signals[DRAW_PAGE], 0, 
+                print_context, page_nr);
+
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING)
+    gtk_print_operation_draw_page_finish (op);
+}
+
+static void
+prepare_data (PrintPagesData *data)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+  GtkPageSetup             *page_setup;
+  gboolean                  paginated = FALSE;
+  int                       i, j, counter;
+
+  if (priv->manual_collation)
+    {
+      data->uncollated_copies = priv->manual_num_copies;
+      data->collated_copies = 1;
+    }
+  else
+    {
+      data->uncollated_copies = 1;
+      data->collated_copies = priv->manual_num_copies;
+    }
+
+  if (!data->initialized)
+    {
+      data->initialized = TRUE;
+      page_setup = create_page_setup (data->op);
+      _gtk_print_context_set_page_setup (priv->print_context,
+                                         page_setup);
+      g_object_unref (page_setup);
+
+      g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
+
+      return;
+    }
+
+  g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
+  if (!paginated)
+    return;
+
+  /* Initialize parts of PrintPagesData that depend on nr_of_pages
+   */
+  if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
+    {
+      if (priv->page_ranges == NULL) 
+        {
+          g_warning ("no pages to print");
+          priv->cancelled = TRUE;
+          return;
+        }
+      data->ranges = priv->page_ranges;
+      data->num_ranges = priv->num_page_ranges;
+      for (i = 0; i < data->num_ranges; i++)
+        if (data->ranges[i].end == -1 || 
+            data->ranges[i].end >= priv->nr_of_pages)
+          data->ranges[i].end = priv->nr_of_pages - 1;
+    }
+  else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
+   priv->current_page != -1)
+    {
+      data->ranges = &data->one_range;
+      data->num_ranges = 1;
+      data->ranges[0].start = priv->current_page;
+      data->ranges[0].end = priv->current_page;
+    }
+  else
+    {
+      data->ranges = &data->one_range;
+      data->num_ranges = 1;
+      data->ranges[0].start = 0;
+      data->ranges[0].end = priv->nr_of_pages - 1;
+    }
+
+  clamp_page_ranges (data);
+
+  if (data->num_ranges < 1) 
+    {
+      priv->cancelled = TRUE;
+      return;
+    }
+
+  priv->nr_of_pages_to_print = 0;
+  for (i = 0; i < data->num_ranges; i++)
+    priv->nr_of_pages_to_print += data->ranges[i].end - data->ranges[i].start + 1;
+
+  data->pages = g_new (int, priv->nr_of_pages_to_print);
+  counter = 0;
+  for (i = 0; i < data->num_ranges; i++)
+    for (j = data->ranges[i].start; j <= data->ranges[i].end; j++)
+      {
+        data->pages[counter] = j;
+        counter++;
+      }
+
+  data->total = -1;
+  data->collated = 0;
+  data->uncollated = 0;
+
+  if (priv->manual_number_up > 1)
+    {
+      if (priv->nr_of_pages_to_print % priv->manual_number_up == 0)
+        data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up;
+      else
+        data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up + 1;
+    }
+  else
+    data->num_of_sheets = priv->nr_of_pages_to_print;
+
+  if (priv->manual_reverse)
+    {
+      /* data->sheet is 0-based */
+      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
+        data->sheet = (data->num_of_sheets - 1) - (data->num_of_sheets - 1) % 2;
+      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
+        data->sheet = (data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2);
+      else
+        data->sheet = data->num_of_sheets - 1;
+    }
+  else
+    {
+      /* data->sheet is 0-based */
+      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
+        data->sheet = 0;
+      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
+        {
+          if (data->num_of_sheets > 1)
+            data->sheet = 1;
+          else
+            data->sheet = -1;
+        }
+      else
+        data->sheet = 0;
+    }
+
+  priv->page_position = data->sheet * priv->manual_number_up;
+
+  if (priv->page_position < 0 || priv->page_position >= priv->nr_of_pages_to_print)
+    {
+      priv->cancelled = TRUE;
+      return;
+    }
+
+  data->page = data->pages[priv->page_position];
+  data->first_position = priv->page_position;
+  data->first_sheet = data->sheet;
+
+  if (priv->manual_reverse)
+    {
+      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
+        data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
+      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
+        data->last_position = MIN (2 * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
+      else
+        data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
+    }
+  else
+    {
+      if (priv->manual_page_set == GTK_PAGE_SET_ODD)
+        data->last_position = MIN (((data->num_of_sheets - 1) - ((data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
+      else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
+        data->last_position = MIN (((data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
+      else
+        data->last_position = priv->nr_of_pages_to_print - 1;
+    }
+
+
+  _gtk_print_operation_set_status (data->op, 
+                                   GTK_PRINT_STATUS_GENERATING_DATA, 
+                                   NULL);
+}
+
+static gboolean
+print_pages_idle (gpointer user_data)
+{
+  PrintPagesData *data = (PrintPagesData*)user_data;
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (data->op);
+  gboolean done = FALSE;
+
+  if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
+    {
+      if (priv->status == GTK_PRINT_STATUS_PREPARING)
+        {
+          prepare_data (data);
+          goto out;
+        }
+
+      if (data->is_preview && !priv->cancelled)
+        {
+          done = TRUE;
+
+          g_signal_emit_by_name (data->op, "ready", priv->print_context);
+          goto out;
+        }
+
+      increment_page_sequence (data);
+
+      if (!data->done)
+        common_render_page (data->op, data->page);
+      else
+        done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
+
+ out:
+
+      if (priv->cancelled)
+        {
+          _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+
+          data->is_preview = FALSE;
+          done = TRUE;
+        }
+
+      if (done && !data->is_preview)
+        {
+          g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
+          priv->end_run (data->op, priv->is_sync, priv->cancelled);
+        }
+
+      update_progress (data);
+    }
+
+  return !done;
+}
+  
+static void
+handle_progress_response (GtkWidget *dialog, 
+                         int        response,
+                         gpointer   data)
+{
+  GtkPrintOperation *op = (GtkPrintOperation *)data;
+
+  gtk_widget_set_visible (dialog, FALSE);
+  gtk_print_operation_cancel (op);
+}
+
+static gboolean
+show_progress_timeout (PrintPagesData *data)
+{
+  gtk_window_present (GTK_WINDOW (data->progress));
+
+  data->op->priv->show_progress_timeout_id = 0;
+
+  return FALSE;
+}
+
+static void
+print_pages (GtkPrintOperation       *op,
+            GtkWindow               *parent,
+            gboolean                 do_print,
+            GtkPrintOperationResult  result)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  PrintPagesData *data;
+  if (!do_print) 
+    {
+      GtkPrintOperationResult tmp_result;
+
+      _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+
+      if (priv->error)
+        tmp_result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      else if (priv->cancelled)
+        tmp_result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+      else
+        tmp_result = result;
+
+      g_signal_emit (op, signals[DONE], 0, tmp_result);
+
+      return;
+  }
+  
+  _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL);  
+
+  data = g_new0 (PrintPagesData, 1);
+  data->op = g_object_ref (op);
+  data->is_preview = (priv->action == GTK_PRINT_OPERATION_ACTION_PREVIEW);
+
+  if (priv->show_progress)
+    {
+      GtkWidget *progress;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+      progress = gtk_message_dialog_new (parent, 0,
+                                         GTK_MESSAGE_OTHER,
+                                         GTK_BUTTONS_CANCEL,
+                                         _("Preparing"));
+G_GNUC_END_IGNORE_DEPRECATIONS
+      g_signal_connect (progress, "response",
+                        G_CALLBACK (handle_progress_response), op);
+
+      priv->show_progress_timeout_id =
+        g_timeout_add (SHOW_PROGRESS_TIME,
+                       (GSourceFunc) show_progress_timeout,
+                       data);
+      gdk_source_set_static_name_by_id (priv->show_progress_timeout_id, "[gtk] show_progress_timeout");
+
+      data->progress = progress;
+    }
+
+  if (data->is_preview)
+    {
+      gboolean handled;
+      
+      g_signal_emit_by_name (op, "preview",
+                            GTK_PRINT_OPERATION_PREVIEW (op),
+                            priv->print_context,
+                            parent,
+                            &handled);
+
+      if (!handled)
+        {
+          GtkWidget *error_dialog;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+          error_dialog = gtk_message_dialog_new (parent,
+                                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                 GTK_MESSAGE_ERROR,
+                                                 GTK_BUTTONS_OK,
+                                                 _("Error creating print preview"));
+
+          gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
+                                                    _("The most probable reason is that a temporary file could not be created."));
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+          if (parent && gtk_window_has_group (parent))
+            gtk_window_group_add_window (gtk_window_get_group (parent),
+                                         GTK_WINDOW (error_dialog));
+
+          g_signal_connect (error_dialog, "response",
+                            G_CALLBACK (gtk_window_destroy), NULL);
+
+          gtk_window_present (GTK_WINDOW (error_dialog));
+
+          print_pages_idle_done (data);
+
+          return;
+        }
+
+      if (gtk_print_context_get_cairo_context (priv->print_context) == NULL)
+        {
+          /* Programmer error */
+          g_error ("You must set a cairo context on the print context");
+        }
+      
+      priv->start_page = preview_start_page;
+      priv->end_page = preview_end_page;
+      priv->end_run = preview_end_run;
+
+      priv->print_pages = gtk_print_settings_get_print_pages (priv->print_settings);
+      priv->page_ranges = gtk_print_settings_get_page_ranges (priv->print_settings,
+                                                             &priv->num_page_ranges);
+      priv->manual_num_copies = 1;
+      priv->manual_collation = FALSE;
+      priv->manual_reverse = gtk_print_settings_get_reverse (priv->print_settings);
+      priv->manual_page_set = gtk_print_settings_get_page_set (priv->print_settings);
+      priv->manual_scale = gtk_print_settings_get_scale (priv->print_settings) / 100.0;
+      priv->manual_orientation = FALSE;
+      priv->manual_number_up = gtk_print_settings_get_number_up (priv->print_settings);
+      priv->manual_number_up_layout = gtk_print_settings_get_number_up_layout (priv->print_settings);
+    }
+  
+  priv->print_pages_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
+                                               print_pages_idle,
+                                               data,
+                                               print_pages_idle_done);
+  gdk_source_set_static_name_by_id (priv->print_pages_idle_id, "[gtk] print_pages_idle");
+  
+  /* Recursive main loop to make sure we don't exit  on sync operations  */
+  if (priv->is_sync)
+    {
+      priv->rloop = g_main_loop_new (NULL, FALSE);
+
+      g_object_ref (op);
+
+      g_main_loop_run (priv->rloop);
+      g_main_loop_unref (priv->rloop);
+      priv->rloop = NULL;
+
+      g_object_unref (op);
+    }
+}
+
+/**
+ * gtk_print_operation_get_error:
+ * @op: a `GtkPrintOperation`
+ * @error: return location for the error
+ *
+ * Call this when the result of a print operation is
+ * %GTK_PRINT_OPERATION_RESULT_ERROR.
+ *
+ * It can be called either after [method@Gtk.PrintOperation.run]
+ * returns, or in the [signal@Gtk.PrintOperation::done] signal
+ * handler.
+ *
+ * The returned `GError` will contain more details on what went wrong.
+ */
+void
+gtk_print_operation_get_error (GtkPrintOperation  *op,
+                              GError            **error)
+{
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  
+  g_propagate_error (error, op->priv->error);
+
+  op->priv->error = NULL;
+}
+
+
+/**
+ * gtk_print_operation_run:
+ * @op: a `GtkPrintOperation`
+ * @action: the action to start
+ * @parent: (nullable): Transient parent of the dialog
+ * @error: (nullable): Return location for errors
+ *
+ * Runs the print operation.
+ *
+ * Normally that this function does not return until the rendering
+ * of all pages is complete. You can connect to the
+ * [signal@Gtk.PrintOperation::status-changed] signal on @op to obtain
+ * some information about the progress of the print operation.
+ *
+ * Furthermore, it may use a recursive mainloop to show the print dialog.
+ *
+ * If you set the [Gtk.PrintOperation:allow-async] property, the operation
+ * will run asynchronously if this is supported on the platform. The
+ * [signal@Gtk.PrintOperation::done] signal will be emitted with the result
+ * of the operation when the it is done (i.e. when the dialog is canceled,
+ * or when the print succeeds or fails).
+ *
+ * ```c
+ * if (settings != NULL)
+ *   gtk_print_operation_set_print_settings (print, settings);
+ *
+ * if (page_setup != NULL)
+ *   gtk_print_operation_set_default_page_setup (print, page_setup);
+ *
+ * g_signal_connect (print, "begin-print",
+ *                   G_CALLBACK (begin_print), &data);
+ * g_signal_connect (print, "draw-page",
+ *                   G_CALLBACK (draw_page), &data);
+ *
+ * res = gtk_print_operation_run (print,
+ *                                GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ *                                parent,
+ *                                &error);
+ *
+ * if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
+ *  {
+ *    error_dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ *                                          GTK_DIALOG_DESTROY_WITH_PARENT,
+ *                                          GTK_MESSAGE_ERROR,
+ *                                          GTK_BUTTONS_CLOSE,
+ *                                          "Error printing file:\n%s",
+ *                                          error->message);
+ *    g_signal_connect (error_dialog, "response",
+ *                      G_CALLBACK (gtk_window_destroy), NULL);
+ *    gtk_window_present (GTK_WINDOW (error_dialog));
+ *    g_error_free (error);
+ *  }
+ * else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
+ *  {
+ *    if (settings != NULL)
+ *     g_object_unref (settings);
+ *    settings = g_object_ref (gtk_print_operation_get_print_settings (print));
+ *  }
+ * ```
+ *
+ * Note that gtk_print_operation_run() can only be called once on a
+ * given `GtkPrintOperation`.
+ *
+ * Returns: the result of the print operation. A return value of
+ *   %GTK_PRINT_OPERATION_RESULT_APPLY indicates that the printing was
+ *   completed successfully. In this case, it is a good idea to obtain
+ *   the used print settings with
+ *   [method@Gtk.PrintOperation.get_print_settings]
+ *   and store them for reuse with the next print operation. A value of
+ *   %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS means the operation is running
+ *   asynchronously, and will emit the [signal@Gtk.PrintOperation::done]
+ *   signal when done.
+ */
+GtkPrintOperationResult
+gtk_print_operation_run (GtkPrintOperation        *op,
+                        GtkPrintOperationAction   action,
+                        GtkWindow                *parent,
+                        GError                  **error)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+  GtkPrintOperationResult result;
+  GtkPageSetup *page_setup;
+  gboolean do_print;
+  gboolean run_print_pages;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
+                        GTK_PRINT_OPERATION_RESULT_ERROR);
+  g_return_val_if_fail (op->priv->status == GTK_PRINT_STATUS_INITIAL,
+                        GTK_PRINT_OPERATION_RESULT_ERROR);
+  
+  run_print_pages = TRUE;
+  do_print = FALSE;
+  priv->error = NULL;
+  priv->action = action;
+
+  if (priv->print_settings == NULL)
+    priv->print_settings = gtk_print_settings_new ();
+  
+  if (action == GTK_PRINT_OPERATION_ACTION_EXPORT)
+    {
+      /* note: if you implement async EXPORT, update the docs
+       * docs for the allow-async property.
+       */
+      priv->is_sync = TRUE;
+      g_return_val_if_fail (priv->export_filename != NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
+      result = run_pdf (op, parent, &do_print);
+    }
+  else if (action == GTK_PRINT_OPERATION_ACTION_PREVIEW)
+    {
+      priv->is_sync = !priv->allow_async;
+      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;
+      result = priv->is_sync ? GTK_PRINT_OPERATION_RESULT_APPLY : GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
+    }
+#ifndef G_OS_WIN32
+  else if (priv->allow_async)
+    {
+      priv->is_sync = FALSE;
+      _gtk_print_operation_platform_backend_run_dialog_async (op,
+                                                             action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                                             parent,
+                                                             print_pages);
+      result = GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
+      run_print_pages = FALSE; /* print_pages is called asynchronously from dialog */
+    }
+#endif
+  else
+    {
+      priv->is_sync = TRUE;
+      result = _gtk_print_operation_platform_backend_run_dialog (op, 
+                                                                action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                                                parent,
+                                                                &do_print);
+    }
+
+  /* To ensure that priv is still valid after print_pages () */
+  g_object_ref (op);
+
+  if (run_print_pages)
+    print_pages (op, parent, do_print, result);
+
+  if (priv->error)
+    {
+      if (error)
+        *error = g_error_copy (priv->error);
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+    }
+  else if (priv->cancelled)
+    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
+  g_object_unref (op);
+  return result;
+}
+
+/**
+ * gtk_print_operation_cancel:
+ * @op: a `GtkPrintOperation`
+ *
+ * Cancels a running print operation.
+ *
+ * This function may be called from a [signal@Gtk.PrintOperation::begin-print],
+ * [signal@Gtk.PrintOperation::paginate] or [signal@Gtk.PrintOperation::draw-page]
+ * signal handler to stop the currently running print operation.
+ */
+void
+gtk_print_operation_cancel (GtkPrintOperation *op)
+{
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  
+  op->priv->cancelled = TRUE;
+}
+
+/**
+ * gtk_print_operation_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
+ * @op: a `GtkPrintOperation`
+ * @support_selection: %TRUE to support selection
+ *
+ * Sets whether selection is supported by `GtkPrintOperation`.
+ */
+void
+gtk_print_operation_set_support_selection (GtkPrintOperation  *op,
+                                           gboolean            support_selection)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  support_selection = support_selection != FALSE;
+  if (priv->support_selection != support_selection)
+    {
+      priv->support_selection = support_selection;
+      g_object_notify (G_OBJECT (op), "support-selection");
+    }
+}
+
+/**
+ * gtk_print_operation_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
+ * @op: a `GtkPrintOperation`
+ *
+ * Gets whether the application supports print of selection
+ *
+ * Returns: whether the application supports print of selection
+ */
+gboolean
+gtk_print_operation_get_support_selection (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
+
+  return priv->support_selection;
+}
+
+/**
+ * gtk_print_operation_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
+ * @op: a `GtkPrintOperation`
+ * @has_selection: %TRUE indicates that a selection exists
+ *
+ * Sets whether there is a selection to print.
+ *
+ * Application has to set number of pages to which the selection
+ * will draw by [method@Gtk.PrintOperation.set_n_pages] in a handler
+ * for the [signal@Gtk.PrintOperation::begin-print] signal.
+ */
+void
+gtk_print_operation_set_has_selection (GtkPrintOperation  *op,
+                                       gboolean            has_selection)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+
+  has_selection = has_selection != FALSE;
+  if (priv->has_selection != has_selection)
+    {
+      priv->has_selection = has_selection;
+      g_object_notify (G_OBJECT (op), "has-selection");
+    }
+}
+
+/**
+ * gtk_print_operation_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
+ * @op: a `GtkPrintOperation`
+ *
+ * Gets whether there is a selection.
+ *
+ * Returns: whether there is a selection
+ */
+gboolean
+gtk_print_operation_get_has_selection (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
+
+  return priv->has_selection;
+}
+
+/**
+ * gtk_print_operation_get_n_pages_to_print: (attributes org.gtk.Method.get_property=n-pages-to-print)
+ * @op: a `GtkPrintOperation`
+ *
+ * Returns the number of pages that will be printed.
+ *
+ * Note that this value is set during print preparation phase
+ * (%GTK_PRINT_STATUS_PREPARING), so this function should never be
+ * called before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
+ * You can connect to the [signal@Gtk.PrintOperation::status-changed]
+ * signal and call gtk_print_operation_get_n_pages_to_print() when
+ * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
+ *
+ * This is typically used to track the progress of print operation.
+ *
+ * Returns: the number of pages that will be printed
+ */
+int
+gtk_print_operation_get_n_pages_to_print (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (op);
+
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), -1);
+
+  return priv->nr_of_pages_to_print;
+}
diff --git a/gtk/print/gtkprintoperationpreview.c b/gtk/print/gtkprintoperationpreview.c
new file mode 100644 (file)
index 0000000..423e352
--- /dev/null
@@ -0,0 +1,186 @@
+/* GTK - The GIMP Toolkit
+ * gtkprintoperationpreview.c: Abstract print preview interface
+ * 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 "gtkprintoperationpreview.h"
+#include "gtkmarshalers.h"
+#include "gtkprivate.h"
+
+
+/**
+ * GtkPrintOperationPreview:
+ *
+ * `GtkPrintOperationPreview` is the interface that is used to
+ * implement print preview.
+ *
+ * A `GtkPrintOperationPreview` object is passed to the
+ * [signal@Gtk.PrintOperation::preview] signal by
+ * [class@Gtk.PrintOperation].
+ */
+
+static void gtk_print_operation_preview_base_init (gpointer g_iface);
+
+GType
+gtk_print_operation_preview_get_type (void)
+{
+  static GType print_operation_preview_type = 0;
+
+  if (!print_operation_preview_type)
+    {
+      const GTypeInfo print_operation_preview_info =
+      {
+        sizeof (GtkPrintOperationPreviewIface), /* class_size */
+       gtk_print_operation_preview_base_init,   /* base_init */
+       NULL,           /* base_finalize */
+       NULL,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       0,
+       0,              /* n_preallocs */
+       NULL
+      };
+
+      print_operation_preview_type =
+       g_type_register_static (G_TYPE_INTERFACE, I_("GtkPrintOperationPreview"),
+                               &print_operation_preview_info, 0);
+
+      g_type_interface_add_prerequisite (print_operation_preview_type, G_TYPE_OBJECT);
+    }
+
+  return print_operation_preview_type;
+}
+
+static void
+gtk_print_operation_preview_base_init (gpointer g_iface)
+{
+  static gboolean initialized = FALSE;
+
+  if (!initialized)
+    {
+      unsigned int id;
+
+      /**
+       * GtkPrintOperationPreview::ready:
+       * @preview: the object on which the signal is emitted
+       * @context: the current `GtkPrintContext`
+       *
+       * The ::ready signal gets emitted once per preview operation,
+       * before the first page is rendered.
+       * 
+       * A handler for this signal can be used for setup tasks.
+       */
+      g_signal_new (I_("ready"),
+                   GTK_TYPE_PRINT_OPERATION_PREVIEW,
+                   G_SIGNAL_RUN_LAST,
+                   G_STRUCT_OFFSET (GtkPrintOperationPreviewIface, ready),
+                   NULL, NULL,
+                   NULL,
+                   G_TYPE_NONE, 1,
+                   GTK_TYPE_PRINT_CONTEXT);
+
+      /**
+       * GtkPrintOperationPreview::got-page-size:
+       * @preview: the object on which the signal is emitted
+       * @context: the current `GtkPrintContext`
+       * @page_setup: the `GtkPageSetup` for the current page
+       *
+       * Emitted once for each page that gets rendered to the preview.
+       *
+       * A handler for this signal should update the @context
+       * according to @page_setup and set up a suitable cairo
+       * context, using [method@Gtk.PrintContext.set_cairo_context].
+       */
+      id = g_signal_new (I_("got-page-size"),
+                         GTK_TYPE_PRINT_OPERATION_PREVIEW,
+                         G_SIGNAL_RUN_LAST,
+                         G_STRUCT_OFFSET (GtkPrintOperationPreviewIface, got_page_size),
+                         NULL, NULL,
+                         _gtk_marshal_VOID__OBJECT_OBJECT,
+                         G_TYPE_NONE, 2,
+                         GTK_TYPE_PRINT_CONTEXT,
+                         GTK_TYPE_PAGE_SETUP);
+      g_signal_set_va_marshaller (id,
+                                  GTK_TYPE_PRINT_OPERATION_PREVIEW,
+                                  _gtk_marshal_VOID__OBJECT_OBJECTv);
+
+      initialized = TRUE;
+    }
+}
+
+/**
+ * gtk_print_operation_preview_render_page:
+ * @preview: a `GtkPrintOperationPreview`
+ * @page_nr: the page to render
+ *
+ * Renders a page to the preview.
+ *
+ * This is using the print context that was passed to the
+ * [signal@Gtk.PrintOperation::preview] handler together
+ * with @preview.
+ *
+ * A custom print preview should use this function to render
+ * the currently selected page.
+ *
+ * Note that this function requires a suitable cairo context to
+ * be associated with the print context.
+ */
+void    
+gtk_print_operation_preview_render_page (GtkPrintOperationPreview *preview,
+                                        int                       page_nr)
+{
+  g_return_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview));
+
+  GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->render_page (preview,
+                                                               page_nr);
+}
+
+/**
+ * gtk_print_operation_preview_end_preview:
+ * @preview: a `GtkPrintOperationPreview`
+ *
+ * Ends a preview.
+ *
+ * This function must be called to finish a custom print preview.
+ */
+void
+gtk_print_operation_preview_end_preview (GtkPrintOperationPreview *preview)
+{
+  g_return_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview));
+
+  GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->end_preview (preview);
+}
+
+/**
+ * gtk_print_operation_preview_is_selected:
+ * @preview: a `GtkPrintOperationPreview`
+ * @page_nr: a page number
+ *
+ * Returns whether the given page is included in the set of pages that
+ * have been selected for printing.
+ *
+ * Returns: %TRUE if the page has been selected for printing
+ */
+gboolean
+gtk_print_operation_preview_is_selected (GtkPrintOperationPreview *preview,
+                                        int                       page_nr)
+{
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION_PREVIEW (preview), FALSE);
+
+  return GTK_PRINT_OPERATION_PREVIEW_GET_IFACE (preview)->is_selected (preview, page_nr);
+}
diff --git a/gtk/print/gtkprintsettings.c b/gtk/print/gtkprintsettings.c
new file mode 100644 (file)
index 0000000..5daa6e6
--- /dev/null
@@ -0,0 +1,1866 @@
+/* GTK - The GIMP Toolkit
+ * gtkprintsettings.c: Print Settings
+ * 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 <stdlib.h>
+
+#include <glib/gprintf.h>
+
+#include "gtkprintsettings.h"
+#include "gtkprintutilsprivate.h"
+#include "gtktypebuiltins.h"
+#include "gtkwidget.h"
+
+
+/**
+ * GtkPrintSettings:
+ *
+ * A `GtkPrintSettings` object represents the settings of a print dialog in
+ * a system-independent way.
+ *
+ * The main use for this object is that once you’ve printed you can get a
+ * settings object that represents the settings the user chose, and the next
+ * time you print you can pass that object in so that the user doesn’t have
+ * to re-set all his settings.
+ *
+ * Its also possible to enumerate the settings so that you can easily save
+ * the settings for the next time your app runs, or even store them in a
+ * document. The predefined keys try to use shared values as much as possible
+ * so that moving such a document between systems still works.
+ */
+
+typedef struct _GtkPrintSettingsClass GtkPrintSettingsClass;
+
+#define GTK_IS_PRINT_SETTINGS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_SETTINGS))
+#define GTK_PRINT_SETTINGS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_SETTINGS, GtkPrintSettingsClass))
+#define GTK_PRINT_SETTINGS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_SETTINGS, GtkPrintSettingsClass))
+
+struct _GtkPrintSettings
+{
+  GObject parent_instance;
+
+  GHashTable *hash;
+};
+
+struct _GtkPrintSettingsClass
+{
+  GObjectClass parent_class;
+};
+
+#define KEYFILE_GROUP_NAME "Print Settings"
+
+G_DEFINE_TYPE (GtkPrintSettings, gtk_print_settings, G_TYPE_OBJECT)
+
+static void
+gtk_print_settings_finalize (GObject *object)
+{
+  GtkPrintSettings *settings = GTK_PRINT_SETTINGS (object);
+
+  g_hash_table_destroy (settings->hash);
+
+  G_OBJECT_CLASS (gtk_print_settings_parent_class)->finalize (object);
+}
+
+static void
+gtk_print_settings_init (GtkPrintSettings *settings)
+{
+  settings->hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                         g_free, g_free);
+}
+
+static void
+gtk_print_settings_class_init (GtkPrintSettingsClass *class)
+{
+  GObjectClass *gobject_class = (GObjectClass *)class;
+
+  gobject_class->finalize = gtk_print_settings_finalize;
+}
+
+/**
+ * gtk_print_settings_new:
+ *
+ * Creates a new `GtkPrintSettings` object.
+ *
+ * Returns: a new `GtkPrintSettings` object
+ */
+GtkPrintSettings *
+gtk_print_settings_new (void)
+{
+  return g_object_new (GTK_TYPE_PRINT_SETTINGS, NULL);
+}
+
+static void
+copy_hash_entry  (gpointer  key,
+                 gpointer  value,
+                 gpointer  user_data)
+{
+  GtkPrintSettings *settings = user_data;
+
+  g_hash_table_insert (settings->hash, 
+                      g_strdup (key), 
+                      g_strdup (value));
+}
+
+
+
+/**
+ * gtk_print_settings_copy:
+ * @other: a `GtkPrintSettings`
+ *
+ * Copies a `GtkPrintSettings` object.
+ *
+ * Returns: (transfer full): a newly allocated copy of @other
+ */
+GtkPrintSettings *
+gtk_print_settings_copy (GtkPrintSettings *other)
+{
+  GtkPrintSettings *settings;
+
+  if (other == NULL)
+    return NULL;
+  
+  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (other), NULL);
+
+  settings = gtk_print_settings_new ();
+
+  g_hash_table_foreach (other->hash,
+                       copy_hash_entry,
+                       settings);
+
+  return settings;
+}
+
+/**
+ * gtk_print_settings_get:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Looks up the string value associated with @key.
+ *
+ * Returns: (nullable): the string value for @key
+ */
+const char *
+gtk_print_settings_get (GtkPrintSettings *settings,
+                       const char       *key)
+{
+  return g_hash_table_lookup (settings->hash, key);
+}
+
+/**
+ * gtk_print_settings_set:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @value: (nullable): a string value
+ *
+ * Associates @value with @key.
+ */
+void
+gtk_print_settings_set (GtkPrintSettings *settings,
+                       const char       *key,
+                       const char       *value)
+{
+  if (value == NULL)
+    gtk_print_settings_unset (settings, key);
+  else
+    g_hash_table_insert (settings->hash, 
+                        g_strdup (key), 
+                        g_strdup (value));
+}
+
+/**
+ * gtk_print_settings_unset:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Removes any value associated with @key.
+ *
+ * This has the same effect as setting the value to %NULL.
+ */
+void
+gtk_print_settings_unset (GtkPrintSettings *settings,
+                         const char       *key)
+{
+  g_hash_table_remove (settings->hash, key);
+}
+
+/**
+ * gtk_print_settings_has_key:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Returns %TRUE, if a value is associated with @key.
+ *
+ * Returns: %TRUE, if @key has a value
+ */
+gboolean        
+gtk_print_settings_has_key (GtkPrintSettings *settings,
+                           const char       *key)
+{
+  return gtk_print_settings_get (settings, key) != NULL;
+}
+
+
+/**
+ * gtk_print_settings_get_bool:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Returns the boolean represented by the value
+ * that is associated with @key.
+ *
+ * The string “true” represents %TRUE, any other
+ * string %FALSE.
+ *
+ * Returns: %TRUE, if @key maps to a true value.
+ */
+gboolean
+gtk_print_settings_get_bool (GtkPrintSettings *settings,
+                            const char       *key)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, key);
+  if (g_strcmp0 (val, "true") == 0)
+    return TRUE;
+  
+  return FALSE;
+}
+
+/**
+ * gtk_print_settings_get_bool_with_default:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @default_val: the default value
+ *
+ * Returns the boolean represented by the value
+ * that is associated with @key, or @default_val
+ * if the value does not represent a boolean.
+ *
+ * The string “true” represents %TRUE, the string
+ * “false” represents %FALSE.
+ *
+ * Returns: the boolean value associated with @key
+ */
+static gboolean
+gtk_print_settings_get_bool_with_default (GtkPrintSettings *settings,
+                                         const char       *key,
+                                         gboolean          default_val)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, key);
+  if (g_strcmp0 (val, "true") == 0)
+    return TRUE;
+
+  if (g_strcmp0 (val, "false") == 0)
+    return FALSE;
+  
+  return default_val;
+}
+
+/**
+ * gtk_print_settings_set_bool:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @value: a boolean
+ *
+ * Sets @key to a boolean value.
+ */
+void
+gtk_print_settings_set_bool (GtkPrintSettings *settings,
+                            const char       *key,
+                            gboolean          value)
+{
+  if (value)
+    gtk_print_settings_set (settings, key, "true");
+  else
+    gtk_print_settings_set (settings, key, "false");
+}
+
+/**
+ * gtk_print_settings_get_double_with_default:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @def: the default value
+ *
+ * Returns the floating point number represented by
+ * the value that is associated with @key, or @default_val
+ * if the value does not represent a floating point number.
+ *
+ * Floating point numbers are parsed with g_ascii_strtod().
+ *
+ * Returns: the floating point number associated with @key
+ */
+double
+gtk_print_settings_get_double_with_default (GtkPrintSettings *settings,
+                                           const char       *key,
+                                           double            def)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, key);
+  if (val == NULL)
+    return def;
+
+  return g_ascii_strtod (val, NULL);
+}
+
+/**
+ * gtk_print_settings_get_double:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Returns the double value associated with @key, or 0.
+ *
+ * Returns: the double value of @key
+ */
+double
+gtk_print_settings_get_double (GtkPrintSettings *settings,
+                              const char       *key)
+{
+  return gtk_print_settings_get_double_with_default (settings, key, 0.0);
+}
+
+/**
+ * gtk_print_settings_set_double:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @value: a double value
+ *
+ * Sets @key to a double value.
+ */
+void
+gtk_print_settings_set_double (GtkPrintSettings *settings,
+                              const char       *key,
+                              double            value)
+{
+  char buf[G_ASCII_DTOSTR_BUF_SIZE];
+  
+  g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, value);
+  gtk_print_settings_set (settings, key, buf);
+}
+
+/**
+ * gtk_print_settings_get_length:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @unit: the unit of the return value
+ *
+ * Returns the value associated with @key, interpreted
+ * as a length.
+ *
+ * The returned value is converted to @units.
+ *
+ * Returns: the length value of @key, converted to @unit
+ */
+double
+gtk_print_settings_get_length (GtkPrintSettings *settings,
+                              const char       *key,
+                              GtkUnit           unit)
+{
+  double length = gtk_print_settings_get_double (settings, key);
+  return _gtk_print_convert_from_mm (length, unit);
+}
+
+/**
+ * gtk_print_settings_set_length:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @value: a length
+ * @unit: the unit of @length
+ *
+ * Associates a length in units of @unit with @key.
+ */
+void
+gtk_print_settings_set_length (GtkPrintSettings *settings,
+                              const char       *key,
+                              double            value, 
+                              GtkUnit           unit)
+{
+  gtk_print_settings_set_double (settings, key,
+                                _gtk_print_convert_to_mm (value, unit));
+}
+
+/**
+ * gtk_print_settings_get_int_with_default:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @def: the default value
+ *
+ * Returns the value of @key, interpreted as
+ * an integer, or the default value.
+ *
+ * Returns: the integer value of @key
+ */
+int
+gtk_print_settings_get_int_with_default (GtkPrintSettings *settings,
+                                        const char       *key,
+                                        int               def)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, key);
+  if (val == NULL)
+    return def;
+
+  return atoi (val);
+}
+
+/**
+ * gtk_print_settings_get_int:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ *
+ * Returns the integer value of @key, or 0.
+ *
+ * Returns: the integer value of @key
+ */
+int
+gtk_print_settings_get_int (GtkPrintSettings *settings,
+                           const char       *key)
+{
+  return gtk_print_settings_get_int_with_default (settings, key, 0);
+}
+
+/**
+ * gtk_print_settings_set_int:
+ * @settings: a `GtkPrintSettings`
+ * @key: a key
+ * @value: an integer
+ *
+ * Sets @key to an integer value.
+ */
+void
+gtk_print_settings_set_int (GtkPrintSettings *settings,
+                           const char       *key,
+                           int               value)
+{
+  char buf[128];
+  g_sprintf (buf, "%d", value);
+  gtk_print_settings_set (settings, key, buf);
+}
+
+/**
+ * gtk_print_settings_foreach:
+ * @settings: a `GtkPrintSettings`
+ * @func: (scope call): the function to call
+ * @user_data: (closure): user data for @func
+ *
+ * Calls @func for each key-value pair of @settings.
+ */
+void
+gtk_print_settings_foreach (GtkPrintSettings    *settings,
+                           GtkPrintSettingsFunc func,
+                           gpointer             user_data)
+{
+  g_hash_table_foreach (settings->hash, (GHFunc)func, user_data);
+}
+
+/**
+ * gtk_print_settings_get_printer:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Convenience function to obtain the value of
+ * %GTK_PRINT_SETTINGS_PRINTER.
+ *
+ * Returns: (nullable): the printer name
+ */
+const char *
+gtk_print_settings_get_printer (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PRINTER);
+}
+
+
+/**
+ * gtk_print_settings_set_printer:
+ * @settings: a `GtkPrintSettings`
+ * @printer: the printer name
+ *
+ * Convenience function to set %GTK_PRINT_SETTINGS_PRINTER
+ * to @printer.
+ */
+void
+gtk_print_settings_set_printer (GtkPrintSettings *settings,
+                               const char       *printer)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PRINTER, printer);
+}
+
+/**
+ * gtk_print_settings_get_orientation:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Get the value of %GTK_PRINT_SETTINGS_ORIENTATION,
+ * converted to a `GtkPageOrientation`.
+ *
+ * Returns: the orientation
+ */
+GtkPageOrientation
+gtk_print_settings_get_orientation (GtkPrintSettings *settings)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_ORIENTATION);
+
+  if (val == NULL || strcmp (val, "portrait") == 0)
+    return GTK_PAGE_ORIENTATION_PORTRAIT;
+
+  if (strcmp (val, "landscape") == 0)
+    return GTK_PAGE_ORIENTATION_LANDSCAPE;
+  
+  if (strcmp (val, "reverse_portrait") == 0)
+    return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
+  
+  if (strcmp (val, "reverse_landscape") == 0)
+    return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
+  
+  return GTK_PAGE_ORIENTATION_PORTRAIT;
+}
+
+/**
+ * gtk_print_settings_set_orientation:
+ * @settings: a `GtkPrintSettings`
+ * @orientation: a page orientation
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_ORIENTATION.
+ */
+void
+gtk_print_settings_set_orientation (GtkPrintSettings   *settings,
+                                   GtkPageOrientation  orientation)
+{
+  const char *val;
+
+  switch (orientation)
+    {
+    case GTK_PAGE_ORIENTATION_LANDSCAPE:
+      val = "landscape";
+      break;
+    default:
+    case GTK_PAGE_ORIENTATION_PORTRAIT:
+      val = "portrait";
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
+      val = "reverse_landscape";
+      break;
+    case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
+      val = "reverse_portrait";
+      break;
+    }
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_ORIENTATION, val);
+}
+
+/**
+ * gtk_print_settings_get_paper_size:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PAPER_FORMAT,
+ * converted to a `GtkPaperSize`.
+ *
+ * Returns: (nullable): the paper size
+ */
+GtkPaperSize *     
+gtk_print_settings_get_paper_size (GtkPrintSettings *settings)
+{
+  const char *val;
+  const char *name;
+  double w, h;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT);
+  if (val == NULL)
+    return NULL;
+
+  if (g_str_has_prefix (val, "custom-")) 
+    {
+      name = val + strlen ("custom-");
+      w = gtk_print_settings_get_paper_width (settings, GTK_UNIT_MM);
+      h = gtk_print_settings_get_paper_height (settings, GTK_UNIT_MM);
+      return gtk_paper_size_new_custom (name, name, w, h, GTK_UNIT_MM);
+    }
+
+  return gtk_paper_size_new (val);
+}
+
+/**
+ * gtk_print_settings_set_paper_size:
+ * @settings: a `GtkPrintSettings`
+ * @paper_size: a paper size
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PAPER_FORMAT,
+ * %GTK_PRINT_SETTINGS_PAPER_WIDTH and
+ * %GTK_PRINT_SETTINGS_PAPER_HEIGHT.
+ */
+void
+gtk_print_settings_set_paper_size (GtkPrintSettings *settings,
+                                  GtkPaperSize     *paper_size)
+{
+  char *custom_name;
+
+  if (paper_size == NULL) 
+    {
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, NULL);
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, NULL);
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_HEIGHT, NULL);
+    }
+  else if (gtk_paper_size_is_custom (paper_size)) 
+    {
+      custom_name = g_strdup_printf ("custom-%s", 
+                                    gtk_paper_size_get_name (paper_size));
+      gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, custom_name);
+      g_free (custom_name);
+      gtk_print_settings_set_paper_width (settings, 
+                                         gtk_paper_size_get_width (paper_size, 
+                                                                   GTK_UNIT_MM),
+                                         GTK_UNIT_MM);
+      gtk_print_settings_set_paper_height (settings, 
+                                          gtk_paper_size_get_height (paper_size, 
+                                                                     GTK_UNIT_MM),
+                                          GTK_UNIT_MM);
+    } 
+  else
+    gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAPER_FORMAT, 
+                           gtk_paper_size_get_name (paper_size));
+}
+
+/**
+ * gtk_print_settings_get_paper_width:
+ * @settings: a `GtkPrintSettings`
+ * @unit: the unit for the return value
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PAPER_WIDTH,
+ * converted to @unit.
+ *
+ * Returns: the paper width, in units of @unit
+ */
+double
+gtk_print_settings_get_paper_width (GtkPrintSettings *settings,
+                                   GtkUnit           unit)
+{
+  return gtk_print_settings_get_length (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, unit);
+}
+
+/**
+ * gtk_print_settings_set_paper_width:
+ * @settings: a `GtkPrintSettings`
+ * @width: the paper width
+ * @unit: the units of @width
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PAPER_WIDTH.
+ */
+void
+gtk_print_settings_set_paper_width (GtkPrintSettings *settings,
+                                   double            width, 
+                                   GtkUnit           unit)
+{
+  gtk_print_settings_set_length (settings, GTK_PRINT_SETTINGS_PAPER_WIDTH, width, unit);
+}
+
+/**
+ * gtk_print_settings_get_paper_height:
+ * @settings: a `GtkPrintSettings`
+ * @unit: the unit for the return value
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PAPER_HEIGHT,
+ * converted to @unit.
+ *
+ * Returns: the paper height, in units of @unit
+ */
+double
+gtk_print_settings_get_paper_height (GtkPrintSettings *settings,
+                                    GtkUnit           unit)
+{
+  return gtk_print_settings_get_length (settings, 
+                                       GTK_PRINT_SETTINGS_PAPER_HEIGHT,
+                                       unit);
+}
+
+/**
+ * gtk_print_settings_set_paper_height:
+ * @settings: a `GtkPrintSettings`
+ * @height: the paper height
+ * @unit: the units of @height
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PAPER_HEIGHT.
+ */
+void
+gtk_print_settings_set_paper_height (GtkPrintSettings *settings,
+                                    double            height, 
+                                    GtkUnit           unit)
+{
+  gtk_print_settings_set_length (settings, 
+                                GTK_PRINT_SETTINGS_PAPER_HEIGHT, 
+                                height, unit);
+}
+
+/**
+ * gtk_print_settings_get_use_color:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_USE_COLOR.
+ *
+ * Returns: whether to use color
+ */
+gboolean
+gtk_print_settings_get_use_color (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_bool_with_default (settings, 
+                                                  GTK_PRINT_SETTINGS_USE_COLOR,
+                                                  TRUE);
+}
+
+/**
+ * gtk_print_settings_set_use_color:
+ * @settings: a `GtkPrintSettings`
+ * @use_color: whether to use color
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_USE_COLOR.
+ */
+void
+gtk_print_settings_set_use_color (GtkPrintSettings *settings,
+                                 gboolean          use_color)
+{
+  gtk_print_settings_set_bool (settings,
+                              GTK_PRINT_SETTINGS_USE_COLOR, 
+                              use_color);
+}
+
+/**
+ * gtk_print_settings_get_collate:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_COLLATE.
+ *
+ * Returns: whether to collate the printed pages
+ */
+gboolean
+gtk_print_settings_get_collate (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_bool_with_default (settings,
+                                                   GTK_PRINT_SETTINGS_COLLATE,
+                                                   TRUE);
+}
+
+/**
+ * gtk_print_settings_set_collate:
+ * @settings: a `GtkPrintSettings`
+ * @collate: whether to collate the output
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_COLLATE.
+ */
+void
+gtk_print_settings_set_collate (GtkPrintSettings *settings,
+                               gboolean          collate)
+{
+  gtk_print_settings_set_bool (settings,
+                              GTK_PRINT_SETTINGS_COLLATE, 
+                              collate);
+}
+
+/**
+ * gtk_print_settings_get_reverse:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_REVERSE.
+ *
+ * Returns:  whether to reverse the order of the printed pages
+ */
+gboolean
+gtk_print_settings_get_reverse (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_bool (settings, 
+                                     GTK_PRINT_SETTINGS_REVERSE);
+}
+
+/**
+ * gtk_print_settings_set_reverse:
+ * @settings: a `GtkPrintSettings`
+ * @reverse: whether to reverse the output
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_REVERSE.
+ */
+void
+gtk_print_settings_set_reverse (GtkPrintSettings *settings,
+                                 gboolean        reverse)
+{
+  gtk_print_settings_set_bool (settings,
+                              GTK_PRINT_SETTINGS_REVERSE, 
+                              reverse);
+}
+
+/**
+ * gtk_print_settings_get_duplex:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_DUPLEX.
+ *
+ * Returns: whether to print the output in duplex.
+ */
+GtkPrintDuplex
+gtk_print_settings_get_duplex (GtkPrintSettings *settings)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DUPLEX);
+
+  if (val == NULL || (strcmp (val, "simplex") == 0))
+    return GTK_PRINT_DUPLEX_SIMPLEX;
+
+  if (strcmp (val, "horizontal") == 0)
+    return GTK_PRINT_DUPLEX_HORIZONTAL;
+  
+  if (strcmp (val, "vertical") == 0)
+    return GTK_PRINT_DUPLEX_VERTICAL;
+  
+  return GTK_PRINT_DUPLEX_SIMPLEX;
+}
+
+/**
+ * gtk_print_settings_set_duplex:
+ * @settings: a `GtkPrintSettings`
+ * @duplex: a `GtkPrintDuplex` value
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_DUPLEX.
+ */
+void
+gtk_print_settings_set_duplex (GtkPrintSettings *settings,
+                              GtkPrintDuplex    duplex)
+{
+  const char *str;
+
+  switch (duplex)
+    {
+    default:
+    case GTK_PRINT_DUPLEX_SIMPLEX:
+      str = "simplex";
+      break;
+    case GTK_PRINT_DUPLEX_HORIZONTAL:
+      str = "horizontal";
+      break;
+    case GTK_PRINT_DUPLEX_VERTICAL:
+      str = "vertical";
+      break;
+    }
+  
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DUPLEX, str);
+}
+
+/**
+ * gtk_print_settings_get_quality:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_QUALITY.
+ *
+ * Returns: the print quality
+ */
+GtkPrintQuality
+gtk_print_settings_get_quality (GtkPrintSettings *settings)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_QUALITY);
+
+  if (val == NULL || (strcmp (val, "normal") == 0))
+    return GTK_PRINT_QUALITY_NORMAL;
+
+  if (strcmp (val, "high") == 0)
+    return GTK_PRINT_QUALITY_HIGH;
+  
+  if (strcmp (val, "low") == 0)
+    return GTK_PRINT_QUALITY_LOW;
+  
+  if (strcmp (val, "draft") == 0)
+    return GTK_PRINT_QUALITY_DRAFT;
+  
+  return GTK_PRINT_QUALITY_NORMAL;
+}
+
+/**
+ * gtk_print_settings_set_quality:
+ * @settings: a `GtkPrintSettings`
+ * @quality: a `GtkPrintQuality` value
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_QUALITY.
+ */
+void
+gtk_print_settings_set_quality (GtkPrintSettings *settings,
+                               GtkPrintQuality   quality)
+{
+  const char *str;
+
+  switch (quality)
+    {
+    default:
+    case GTK_PRINT_QUALITY_NORMAL:
+      str = "normal";
+      break;
+    case GTK_PRINT_QUALITY_HIGH:
+      str = "high";
+      break;
+    case GTK_PRINT_QUALITY_LOW:
+      str = "low";
+      break;
+    case GTK_PRINT_QUALITY_DRAFT:
+      str = "draft";
+      break;
+    }
+  
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_QUALITY, str);
+}
+
+/**
+ * gtk_print_settings_get_page_set:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PAGE_SET.
+ *
+ * Returns: the set of pages to print
+ */
+GtkPageSet
+gtk_print_settings_get_page_set (GtkPrintSettings *settings)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAGE_SET);
+
+  if (val == NULL || (strcmp (val, "all") == 0))
+    return GTK_PAGE_SET_ALL;
+
+  if (strcmp (val, "even") == 0)
+    return GTK_PAGE_SET_EVEN;
+  
+  if (strcmp (val, "odd") == 0)
+    return GTK_PAGE_SET_ODD;
+  
+  return GTK_PAGE_SET_ALL;
+}
+
+/**
+ * gtk_print_settings_set_page_set:
+ * @settings: a `GtkPrintSettings`
+ * @page_set: a `GtkPageSet` value
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PAGE_SET.
+ */
+void
+gtk_print_settings_set_page_set (GtkPrintSettings *settings,
+                                GtkPageSet        page_set)
+{
+  const char *str;
+
+  switch (page_set)
+    {
+    default:
+    case GTK_PAGE_SET_ALL:
+      str = "all";
+      break;
+    case GTK_PAGE_SET_EVEN:
+      str = "even";
+      break;
+    case GTK_PAGE_SET_ODD:
+      str = "odd";
+      break;
+    }
+  
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAGE_SET, str);
+}
+
+/**
+ * gtk_print_settings_get_number_up_layout:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT.
+ *
+ * Returns: layout of page in number-up mode
+ */
+GtkNumberUpLayout
+gtk_print_settings_get_number_up_layout (GtkPrintSettings *settings)
+{
+  GtkNumberUpLayout layout;
+  GtkTextDirection  text_direction;
+  GEnumClass       *enum_class;
+  GEnumValue       *enum_value;
+  const char       *val;
+
+  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT);
+  text_direction = gtk_widget_get_default_direction ();
+
+  if (text_direction == 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;
+
+  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;
+}
+
+/**
+ * gtk_print_settings_set_number_up_layout:
+ * @settings: a `GtkPrintSettings`
+ * @number_up_layout: a `GtkNumberUpLayout` value
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT.
+ */
+void
+gtk_print_settings_set_number_up_layout (GtkPrintSettings  *settings,
+                                        GtkNumberUpLayout  number_up_layout)
+{
+  GEnumClass *enum_class;
+  GEnumValue *enum_value;
+
+  g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
+
+  enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
+  enum_value = g_enum_get_value (enum_class, number_up_layout);
+  g_return_if_fail (enum_value != NULL);
+
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, enum_value->value_nick);
+  g_type_class_unref (enum_class);
+}
+
+/**
+ * gtk_print_settings_get_n_copies:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_N_COPIES.
+ * 
+ * Returns: the number of copies to print
+ */
+int
+gtk_print_settings_get_n_copies (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_N_COPIES, 1);
+}
+
+/**
+ * gtk_print_settings_set_n_copies:
+ * @settings: a `GtkPrintSettings`
+ * @num_copies: the number of copies
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_N_COPIES.
+ */
+void
+gtk_print_settings_set_n_copies (GtkPrintSettings *settings,
+                                int               num_copies)
+{
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_N_COPIES,
+                             num_copies);
+}
+
+/**
+ * gtk_print_settings_get_number_up:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_NUMBER_UP.
+ *
+ * Returns: the number of pages per sheet
+ */
+int
+gtk_print_settings_get_number_up (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_NUMBER_UP, 1);
+}
+
+/**
+ * gtk_print_settings_set_number_up:
+ * @settings: a `GtkPrintSettings`
+ * @number_up: the number of pages per sheet
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_NUMBER_UP.
+ */
+void
+gtk_print_settings_set_number_up (GtkPrintSettings *settings,
+                                 int               number_up)
+{
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_NUMBER_UP,
+                               number_up);
+}
+
+/**
+ * gtk_print_settings_get_resolution:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION.
+ *
+ * Returns: the resolution in dpi
+ */
+int
+gtk_print_settings_get_resolution (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION, 300);
+}
+
+/**
+ * gtk_print_settings_set_resolution:
+ * @settings: a `GtkPrintSettings`
+ * @resolution: the resolution in dpi
+ *
+ * Sets the values of %GTK_PRINT_SETTINGS_RESOLUTION,
+ * %GTK_PRINT_SETTINGS_RESOLUTION_X and
+ * %GTK_PRINT_SETTINGS_RESOLUTION_Y.
+ */
+void
+gtk_print_settings_set_resolution (GtkPrintSettings *settings,
+                                  int               resolution)
+{
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION,
+                             resolution);
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_X,
+                             resolution);
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y,
+                             resolution);
+}
+
+/**
+ * gtk_print_settings_get_resolution_x:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION_X.
+ *
+ * Returns: the horizontal resolution in dpi
+ */
+int
+gtk_print_settings_get_resolution_x (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_X, 300);
+}
+
+/**
+ * gtk_print_settings_get_resolution_y:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_RESOLUTION_Y.
+ *
+ * Returns: the vertical resolution in dpi
+ */
+int
+gtk_print_settings_get_resolution_y (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y, 300);
+}
+
+/**
+ * gtk_print_settings_set_resolution_xy:
+ * @settings: a `GtkPrintSettings`
+ * @resolution_x: the horizontal resolution in dpi
+ * @resolution_y: the vertical resolution in dpi
+ *
+ * Sets the values of %GTK_PRINT_SETTINGS_RESOLUTION,
+ * %GTK_PRINT_SETTINGS_RESOLUTION_X and
+ * %GTK_PRINT_SETTINGS_RESOLUTION_Y.
+ */
+void
+gtk_print_settings_set_resolution_xy (GtkPrintSettings *settings,
+                                     int               resolution_x,
+                                     int               resolution_y)
+{
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_X,
+                             resolution_x);
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y,
+                             resolution_y);
+  gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_RESOLUTION,
+                             resolution_x);
+}
+
+/**
+ * gtk_print_settings_get_printer_lpi:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PRINTER_LPI.
+ *
+ * Returns: the resolution in lpi (lines per inch)
+ */
+double
+gtk_print_settings_get_printer_lpi (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_double_with_default (settings, GTK_PRINT_SETTINGS_PRINTER_LPI, 150.0);
+}
+
+/**
+ * gtk_print_settings_set_printer_lpi:
+ * @settings: a `GtkPrintSettings`
+ * @lpi: the resolution in lpi (lines per inch)
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PRINTER_LPI.
+ */
+void
+gtk_print_settings_set_printer_lpi (GtkPrintSettings *settings,
+                                   double            lpi)
+{
+  gtk_print_settings_set_double (settings, GTK_PRINT_SETTINGS_PRINTER_LPI,
+                                lpi);
+}
+
+/**
+ * gtk_print_settings_get_scale:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_SCALE.
+ *
+ * Returns: the scale in percent
+ */
+double
+gtk_print_settings_get_scale (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get_double_with_default (settings,
+                                                    GTK_PRINT_SETTINGS_SCALE,
+                                                    100.0);
+}
+
+/**
+ * gtk_print_settings_set_scale:
+ * @settings: a `GtkPrintSettings`
+ * @scale: the scale in percent
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_SCALE.
+ */
+void
+gtk_print_settings_set_scale (GtkPrintSettings *settings,
+                             double            scale)
+{
+  gtk_print_settings_set_double (settings, GTK_PRINT_SETTINGS_SCALE,
+                                scale);
+}
+
+/**
+ * gtk_print_settings_get_print_pages:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_PRINT_PAGES.
+ * 
+ * Returns: which pages to print
+ */
+GtkPrintPages
+gtk_print_settings_get_print_pages (GtkPrintSettings *settings)
+{
+  const char *val;
+
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PRINT_PAGES);
+
+  if (val == NULL || (strcmp (val, "all") == 0))
+    return GTK_PRINT_PAGES_ALL;
+
+  if (strcmp (val, "selection") == 0)
+    return GTK_PRINT_PAGES_SELECTION;
+
+  if (strcmp (val, "current") == 0)
+    return GTK_PRINT_PAGES_CURRENT;
+  
+  if (strcmp (val, "ranges") == 0)
+    return GTK_PRINT_PAGES_RANGES;
+  
+  return GTK_PRINT_PAGES_ALL;
+}
+
+/**
+ * gtk_print_settings_set_print_pages:
+ * @settings: a `GtkPrintSettings`
+ * @pages: a `GtkPrintPages` value
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_PRINT_PAGES.
+ */
+void
+gtk_print_settings_set_print_pages (GtkPrintSettings *settings,
+                                   GtkPrintPages     pages)
+{
+  const char *str;
+
+  switch (pages)
+    {
+    default:
+    case GTK_PRINT_PAGES_ALL:
+      str = "all";
+      break;
+    case GTK_PRINT_PAGES_CURRENT:
+      str = "current";
+      break;
+    case GTK_PRINT_PAGES_SELECTION:
+      str = "selection";
+      break;
+    case GTK_PRINT_PAGES_RANGES:
+      str = "ranges";
+      break;
+    }
+  
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PRINT_PAGES, str);
+}
+
+/**
+ * gtk_print_settings_get_page_ranges:
+ * @settings: a `GtkPrintSettings`
+ * @num_ranges: (out): return location for the length of the returned array
+ *
+ * Gets the value of %GTK_PRINT_SETTINGS_PAGE_RANGES.
+ *
+ * Returns: (array length=num_ranges) (transfer full): an array
+ *   of `GtkPageRange`s. Use g_free() to free the array when
+ *   it is no longer needed.
+ */
+GtkPageRange *
+gtk_print_settings_get_page_ranges (GtkPrintSettings *settings,
+                                   int              *num_ranges)
+{
+  const char *val;
+  char **range_strs;
+  GtkPageRange *ranges;
+  int i, n;
+  
+  val = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_PAGE_RANGES);
+
+  if (val == NULL)
+    {
+      *num_ranges = 0;
+      return NULL;
+    }
+  
+  range_strs = g_strsplit (val, ",", 0);
+
+  for (i = 0; range_strs[i] != NULL; i++)
+    ;
+
+  n = i;
+
+  ranges = g_new0 (GtkPageRange, n);
+
+  for (i = 0; i < n; i++)
+    {
+      int start, end;
+      char *str;
+
+      start = (int)strtol (range_strs[i], &str, 10);
+      end = start;
+
+      if (*str == '-')
+       {
+         str++;
+         end = (int)strtol (str, NULL, 10);
+       }
+
+      ranges[i].start = start;
+      ranges[i].end = end;
+    }
+
+  g_strfreev (range_strs);
+
+  *num_ranges = n;
+  return ranges;
+}
+
+/**
+ * gtk_print_settings_set_page_ranges:
+ * @settings: a `GtkPrintSettings`
+ * @page_ranges: (array length=num_ranges): an array of `GtkPageRange`s
+ * @num_ranges: the length of @page_ranges
+ *
+ * Sets the value of %GTK_PRINT_SETTINGS_PAGE_RANGES.
+ */
+void
+gtk_print_settings_set_page_ranges  (GtkPrintSettings *settings,
+                                    GtkPageRange     *page_ranges,
+                                    int               num_ranges)
+{
+  GString *s;
+  int i;
+  
+  s = g_string_new ("");
+
+  for (i = 0; i < num_ranges; i++)
+    {
+      if (page_ranges[i].start == page_ranges[i].end)
+       g_string_append_printf (s, "%d", page_ranges[i].start);
+      else
+       g_string_append_printf (s, "%d-%d",
+                               page_ranges[i].start,
+                               page_ranges[i].end);
+      if (i < num_ranges - 1)
+       g_string_append (s, ",");
+    }
+
+  
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_PAGE_RANGES, 
+                         s->str);
+
+  g_string_free (s, TRUE);
+}
+
+/**
+ * gtk_print_settings_get_default_source:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_DEFAULT_SOURCE.
+ * 
+ * Returns: (nullable): the default source
+ */
+const char *
+gtk_print_settings_get_default_source (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE);
+}
+
+/**
+ * gtk_print_settings_set_default_source:
+ * @settings: a `GtkPrintSettings`
+ * @default_source: the default source
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_DEFAULT_SOURCE.
+ */
+void
+gtk_print_settings_set_default_source (GtkPrintSettings *settings,
+                                      const char       *default_source)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE, default_source);
+}
+     
+/**
+ * gtk_print_settings_get_media_type:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_MEDIA_TYPE.
+ *
+ * The set of media types is defined in PWG 5101.1-2002 PWG.
+ * 
+ * Returns: (nullable): the media type
+ */
+const char *
+gtk_print_settings_get_media_type (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE);
+}
+
+/**
+ * gtk_print_settings_set_media_type:
+ * @settings: a `GtkPrintSettings`
+ * @media_type: the media type
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_MEDIA_TYPE.
+ * 
+ * The set of media types is defined in PWG 5101.1-2002 PWG.
+ */
+void
+gtk_print_settings_set_media_type (GtkPrintSettings *settings,
+                                  const char       *media_type)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE, media_type);
+}
+
+/**
+ * gtk_print_settings_get_dither:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_DITHER.
+ * 
+ * Returns: (nullable): the dithering that is used
+ */
+const char *
+gtk_print_settings_get_dither (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_DITHER);
+}
+
+/**
+ * gtk_print_settings_set_dither:
+ * @settings: a `GtkPrintSettings`
+ * @dither: the dithering that is used
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_DITHER.
+ */
+void
+gtk_print_settings_set_dither (GtkPrintSettings *settings,
+                              const char       *dither)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_DITHER, dither);
+}
+     
+/**
+ * gtk_print_settings_get_finishings:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_FINISHINGS.
+ * 
+ * Returns: (nullable): the finishings
+ */
+const char *
+gtk_print_settings_get_finishings (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_FINISHINGS);
+}
+
+/**
+ * gtk_print_settings_set_finishings:
+ * @settings: a `GtkPrintSettings`
+ * @finishings: the finishings
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_FINISHINGS.
+ */
+void
+gtk_print_settings_set_finishings (GtkPrintSettings *settings,
+                                  const char       *finishings)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_FINISHINGS, finishings);
+}
+     
+/**
+ * gtk_print_settings_get_output_bin:
+ * @settings: a `GtkPrintSettings`
+ * 
+ * Gets the value of %GTK_PRINT_SETTINGS_OUTPUT_BIN.
+ * 
+ * Returns: (nullable): the output bin
+ */
+const char *
+gtk_print_settings_get_output_bin (GtkPrintSettings *settings)
+{
+  return gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_BIN);
+}
+
+/**
+ * gtk_print_settings_set_output_bin:
+ * @settings: a `GtkPrintSettings`
+ * @output_bin: the output bin
+ * 
+ * Sets the value of %GTK_PRINT_SETTINGS_OUTPUT_BIN.
+ */
+void
+gtk_print_settings_set_output_bin (GtkPrintSettings *settings,
+                                  const char       *output_bin)
+{
+  gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BIN, output_bin);
+}
+
+/**
+ * gtk_print_settings_load_file:
+ * @settings: a `GtkPrintSettings`
+ * @file_name: (type filename): the filename to read the settings from
+ * @error: (nullable): return location for errors
+ *
+ * Reads the print settings from @file_name.
+ *
+ * If the file could not be loaded then error is set to either
+ * a `GFileError` or `GKeyFileError`.
+ *
+ * See [method@Gtk.PrintSettings.to_file].
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_print_settings_load_file (GtkPrintSettings *settings,
+                              const char       *file_name,
+                              GError          **error)
+{
+  gboolean retval = FALSE;
+  GKeyFile *key_file;
+
+  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
+  g_return_val_if_fail (file_name != NULL, FALSE);
+
+  key_file = g_key_file_new ();
+
+  if (g_key_file_load_from_file (key_file, file_name, 0, error) &&
+      gtk_print_settings_load_key_file (settings, key_file, NULL, error))
+    retval = TRUE;
+
+  g_key_file_free (key_file);
+
+  return retval;
+}
+
+/**
+ * gtk_print_settings_new_from_file:
+ * @file_name: (type filename): the filename to read the settings from
+ * @error: (nullable): return location for errors
+ *
+ * Reads the print settings from @file_name.
+ *
+ * Returns a new `GtkPrintSettings` object with the restored settings,
+ * or %NULL if an error occurred. If the file could not be loaded then
+ * error is set to either a `GFileError` or `GKeyFileError`.
+ *
+ * See [method@Gtk.PrintSettings.to_file].
+ *
+ * Returns: the restored `GtkPrintSettings`
+ */
+GtkPrintSettings *
+gtk_print_settings_new_from_file (const char   *file_name,
+                                 GError      **error)
+{
+  GtkPrintSettings *settings = gtk_print_settings_new ();
+
+  if (!gtk_print_settings_load_file (settings, file_name, error))
+    {
+      g_object_unref (settings);
+      settings = NULL;
+    }
+
+  return settings;
+}
+
+/**
+ * gtk_print_settings_load_key_file:
+ * @settings: a `GtkPrintSettings`
+ * @key_file: the `GKeyFile` to retrieve the settings from
+ * @group_name: (nullable): the name of the group to use, or %NULL
+ *   to use the default “Print Settings”
+ * @error: (nullable): return location for errors
+ *
+ * Reads the print settings from the group @group_name in @key_file.
+ *
+ * If the file could not be loaded then error is set to either a
+ * `GFileError` or `GKeyFileError`.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_print_settings_load_key_file (GtkPrintSettings *settings,
+                                 GKeyFile         *key_file,
+                                 const char       *group_name,
+                                 GError          **error)
+{
+  char **keys;
+  gsize n_keys, i;
+  GError *err = NULL;
+
+  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
+  g_return_val_if_fail (key_file != NULL, FALSE);
+
+  if (!group_name)
+    group_name = KEYFILE_GROUP_NAME;
+
+  keys = g_key_file_get_keys (key_file,
+                             group_name,
+                             &n_keys,
+                             &err);
+  if (err != NULL)
+    {
+      g_propagate_error (error, err);
+      return FALSE;
+    }
+   
+  for (i = 0 ; i < n_keys; ++i)
+    {
+      char *value;
+
+      value = g_key_file_get_string (key_file,
+                                    group_name,
+                                    keys[i],
+                                    NULL);
+      if (!value)
+        continue;
+
+      gtk_print_settings_set (settings, keys[i], value);
+      g_free (value);
+    }
+
+  g_strfreev (keys);
+
+  return TRUE;
+}
+
+/**
+ * gtk_print_settings_new_from_key_file:
+ * @key_file: the `GKeyFile` to retrieve the settings from
+ * @group_name: (nullable): the name of the group to use, or %NULL to use
+ *   the default “Print Settings”
+ * @error: (nullable): return location for errors
+ *
+ * Reads the print settings from the group @group_name in @key_file.
+ *
+ * Returns a new `GtkPrintSettings` object with the restored settings,
+ * or %NULL if an error occurred. If the file could not be loaded then
+ * error is set to either `GFileError` or `GKeyFileError`.
+ *
+ * Returns: the restored `GtkPrintSettings`
+ */
+GtkPrintSettings *
+gtk_print_settings_new_from_key_file (GKeyFile     *key_file,
+                                     const char   *group_name,
+                                     GError      **error)
+{
+  GtkPrintSettings *settings = gtk_print_settings_new ();
+
+  if (!gtk_print_settings_load_key_file (settings, key_file,
+                                         group_name, error))
+    {
+      g_object_unref (settings);
+      settings = NULL;
+    }
+
+  return settings;
+}
+
+/**
+ * gtk_print_settings_to_file:
+ * @settings: a `GtkPrintSettings`
+ * @file_name: (type filename): the file to save to
+ * @error: (nullable): return location for errors
+ *
+ * This function saves the print settings from @settings to @file_name.
+ *
+ * If the file could not be written then error is set to either a
+ * `GFileError` or `GKeyFileError`.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+gtk_print_settings_to_file (GtkPrintSettings  *settings,
+                           const char        *file_name,
+                           GError           **error)
+{
+  GKeyFile *key_file;
+  gboolean retval = FALSE;
+  char *data = NULL;
+  gsize len;
+  GError *err = NULL;
+
+  g_return_val_if_fail (GTK_IS_PRINT_SETTINGS (settings), FALSE);
+  g_return_val_if_fail (file_name != NULL, FALSE);
+
+  key_file = g_key_file_new ();
+  gtk_print_settings_to_key_file (settings, key_file, NULL);
+
+  data = g_key_file_to_data (key_file, &len, &err);
+  if (!data)
+    goto out;
+
+  retval = g_file_set_contents (file_name, data, len, &err);
+
+out:
+  if (err != NULL)
+    g_propagate_error (error, err);
+
+  g_key_file_free (key_file);
+  g_free (data);
+
+  return retval;
+}
+
+typedef struct {
+  GKeyFile *key_file;
+  const char *group_name;
+} SettingsData;
+
+static void
+add_value_to_key_file (const char   *key,
+                      const char   *value,
+                      SettingsData *data)
+{
+  g_key_file_set_string (data->key_file, data->group_name, key, value);
+}
+
+/**
+ * gtk_print_settings_to_key_file:
+ * @settings: a `GtkPrintSettings`
+ * @key_file: the `GKeyFile` to save the print settings to
+ * @group_name: (nullable): the group to add the settings to in @key_file, or
+ *   %NULL to use the default “Print Settings”
+ *
+ * This function adds the print settings from @settings to @key_file.
+ */
+void
+gtk_print_settings_to_key_file (GtkPrintSettings  *settings,
+                               GKeyFile          *key_file,
+                               const char        *group_name)
+{
+  SettingsData data;
+
+  g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
+  g_return_if_fail (key_file != NULL);
+
+  if (!group_name)
+    group_name = KEYFILE_GROUP_NAME;
+
+  data.key_file = key_file;
+  data.group_name = group_name;
+
+  gtk_print_settings_foreach (settings,
+                             (GtkPrintSettingsFunc) add_value_to_key_file,
+                             &data);
+}
+
+static void
+add_to_variant (const char *key,
+                const char *value,
+                gpointer     data)
+{
+  GVariantBuilder *builder = data;
+  g_variant_builder_add (builder, "{sv}", key, g_variant_new_string (value));
+}
+
+/**
+ * gtk_print_settings_to_gvariant:
+ * @settings: a `GtkPrintSettings`
+ *
+ * Serialize print settings to an a{sv} variant.
+ *
+ * Returns: (transfer none): a new, floating, `GVariant`
+ */
+GVariant *
+gtk_print_settings_to_gvariant (GtkPrintSettings *settings)
+{
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+  gtk_print_settings_foreach (settings, add_to_variant, &builder);
+
+  return g_variant_builder_end (&builder);
+}
+
+/**
+ * gtk_print_settings_new_from_gvariant:
+ * @variant: an a{sv} `GVariant`
+ *
+ * Deserialize print settings from an a{sv} variant.
+ *
+ * The variant must be in the format produced by
+ * [method@Gtk.PrintSettings.to_gvariant].
+ *
+ * Returns: (transfer full): a new `GtkPrintSettings` object
+ */
+GtkPrintSettings *
+gtk_print_settings_new_from_gvariant (GVariant *variant)
+{
+  GtkPrintSettings *settings;
+  int i;
+
+  g_return_val_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT), NULL);
+
+  settings = gtk_print_settings_new ();
+
+  for (i = 0; i < g_variant_n_children (variant); i++)
+    {
+      const char *key;
+      GVariant *v;
+
+      g_variant_get_child (variant, i, "{&sv}", &key, &v);
+      if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
+        gtk_print_settings_set (settings, key, g_variant_get_string (v, NULL));
+      g_variant_unref (v);
+    }
+
+  return settings;
+}
diff --git a/gtk/print/gtkprintutils.c b/gtk/print/gtkprintutils.c
new file mode 100644 (file)
index 0000000..105ad08
--- /dev/null
@@ -0,0 +1,60 @@
+/* GTK - The GIMP Toolkit
+ * gtkpapersize.c: Paper Size
+ * 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 "gtkprintutilsprivate.h"
+
+double
+_gtk_print_convert_to_mm (double len, 
+                         GtkUnit unit)
+{
+  switch (unit)
+    {
+    case GTK_UNIT_MM:
+      return len;
+    case GTK_UNIT_INCH:
+      return len * MM_PER_INCH;
+    case GTK_UNIT_NONE:
+    default:
+      g_warning ("Unsupported unit");
+      G_GNUC_FALLTHROUGH;
+    case GTK_UNIT_POINTS:
+      return len * (MM_PER_INCH / POINTS_PER_INCH);
+      break;
+    }
+}
+
+double
+_gtk_print_convert_from_mm (double len, 
+                           GtkUnit unit)
+{
+  switch (unit)
+    {
+    case GTK_UNIT_MM:
+      return len;
+    case GTK_UNIT_INCH:
+      return len / MM_PER_INCH;
+    case GTK_UNIT_NONE:
+    default:
+      g_warning ("Unsupported unit");
+      G_GNUC_FALLTHROUGH;
+    case GTK_UNIT_POINTS:
+      return len / (MM_PER_INCH / POINTS_PER_INCH);
+      break;
+    }
+}
index 8028cd520a7bac97287bffd4f160542bf771a3b5..78312aabd6e4148a75b9e2771a0529895d624c50 100644 (file)
@@ -6,3 +6,13 @@ gtk_print_headers = files([
   'gtkprintoperationpreview.h',
   'gtkprintsettings.h',
 ])
+
+gtk_print_sources = files([
+  'gtkpagesetup.c',
+  'gtkpapersize.c',
+  'gtkprintcontext.c',
+  'gtkprintoperation.c',
+  'gtkprintoperationpreview.c',
+  'gtkprintsettings.c',
+  'gtkprintutils.c',
+])