+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* GTK - The GIMP Toolkit
- * gtkprintoperation.c: Print Operation
- * Copyright (C) 2006, Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#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;
-}
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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;
- }
-}
subdir('a11y')
subdir('deprecated')
subdir('inspector')
+subdir('print')
gtk_cargs = [
'-DGTK_COMPILATION',
'gtkplacesviewrow.c',
'gtkpointerfocus.c',
'gtkpopovercontent.c',
- 'gtkprintutils.c',
'gtkprivate.c',
'gtkprogresstracker.c',
'gtkrbtree.c',
'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',
'gtkwindowhandle.c',
])
+gtk_public_sources += gtk_print_sources
+
gtk_private_type_headers = files([
'gtkcsstypesprivate.h',
'gtktexthandleprivate.h',
'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')
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * gtkprintoperation.c: Print Operation
+ * Copyright (C) 2006, Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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;
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+ }
+}
'gtkprintoperationpreview.h',
'gtkprintsettings.h',
])
+
+gtk_print_sources = files([
+ 'gtkpagesetup.c',
+ 'gtkpapersize.c',
+ 'gtkprintcontext.c',
+ 'gtkprintoperation.c',
+ 'gtkprintoperationpreview.c',
+ 'gtkprintsettings.c',
+ 'gtkprintutils.c',
+])