]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkprintoperation.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkprintoperation.c
index 93751ba5e03feae70d9865e2d6a0c3c1f4b0feb1..3fd4f93dc7c0b746515f244dc74e39f08d057e9f 100644 (file)
  * 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 
 #include <errno.h>
-#include <stdlib.h>       
+#include <stdlib.h>
 #include <math.h>
-
 #include <string.h>
+
+#include <cairo-pdf.h>
+
 #include "gtkprintoperation-private.h"
 #include "gtkmarshalers.h"
-#include <cairo-pdf.h>
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtkmessagedialog.h"
-#include "gtkalias.h"
+#include "gtktypebuiltins.h"
+
+/**
+ * SECTION:gtkprintoperation
+ * @Title: GtkPrintOperation
+ * @Short_description: High-level Printing API
+ * @See_also: #GtkPrintContext, #GtkPrintUnixDialog
+ *
+ * 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 #GtkPrintUnixDialog.
+ *
+ * The typical way to use the high-level printing API is to create
+ * a GtkPrintOperation object with gtk_print_operation_new() when
+ * the user selects to print. Then you set some properties on it,
+ * e.g. the page size, any #GtkPrintSettings from previous print
+ * operations, the number of pages, the current page, etc.
+ *
+ * Then you start the print operation by calling gtk_print_operation_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
+ * #GtkPrintOperation::draw-page, which you are supposed to catch
+ * and render the page on the provided #GtkPrintContext using Cairo.
+ *
+ * <example>
+ * <title>The high-level printing API</title>
+ * <programlisting>
+ * 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);
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * 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
+ * gtk_print_operation_preview_render_page(),
+ * gtk_print_operation_preview_end_preview() and
+ * gtk_print_operation_preview_is_selected()
+ * are useful when implementing a print preview.
+ */
 
 #define SHOW_PROGRESS_TIME 1200
 
-#define GTK_PRINT_OPERATION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_PRINT_OPERATION, GtkPrintOperationPrivate))
 
-enum 
+enum
 {
   DONE,
   BEGIN_PRINT,
@@ -78,11 +146,15 @@ enum
 
 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,
-                                        gint                           page_nr);
+static void          preview_iface_init      (GtkPrintOperationPreviewIface *iface);
+static GtkPageSetup *create_page_setup       (GtkPrintOperation             *op);
+static void          common_render_page      (GtkPrintOperation             *op,
+                                             gint                           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,
@@ -152,7 +224,9 @@ gtk_print_operation_init (GtkPrintOperation *operation)
   GtkPrintOperationPrivate *priv;
   const char *appname;
 
-  priv = operation->priv = GTK_PRINT_OPERATION_GET_PRIVATE (operation);
+  priv = operation->priv = G_TYPE_INSTANCE_GET_PRIVATE (operation,
+                                                        GTK_TYPE_PRINT_OPERATION,
+                                                        GtkPrintOperationPrivate);
 
   priv->status = GTK_PRINT_STATUS_INITIAL;
   priv->status_string = g_strdup ("");
@@ -174,7 +248,7 @@ gtk_print_operation_init (GtkPrintOperation *operation)
   priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
 
   priv->rloop = NULL;
-  priv->unit = GTK_UNIT_PIXEL;
+  priv->unit = GTK_UNIT_NONE;
 
   appname = g_get_application_name ();
   if (appname == NULL)
@@ -201,6 +275,7 @@ static void
 preview_iface_end_preview (GtkPrintOperationPreview *preview)
 {
   GtkPrintOperation *op;
+  GtkPrintOperationResult result;
   
   op = GTK_PRINT_OPERATION (preview);
 
@@ -214,7 +289,14 @@ preview_iface_end_preview (GtkPrintOperationPreview *preview)
   
   _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
 
-  g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
+  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
@@ -260,13 +342,23 @@ preview_start_page (GtkPrintOperation *op,
                    GtkPrintContext   *print_context,
                    GtkPageSetup      *page_setup)
 {
-  g_signal_emit_by_name (op, "got-page-size", print_context, 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
@@ -411,6 +503,31 @@ gtk_print_operation_get_property (GObject    *object,
     }
 }
 
+struct _PrintPagesData
+{
+  GtkPrintOperation *op;
+  gint uncollated_copies;
+  gint collated_copies;
+  gint uncollated, collated, total;
+
+  gint range, num_ranges;
+  GtkPageRange *ranges;
+  GtkPageRange one_range;
+
+  gint page;
+  gint sheet;
+  gint first_position, last_position;
+  gint first_sheet;
+  gint num_of_sheets;
+  gint *pages;
+
+  GtkWidget *progress;
+  gboolean initialized;
+  gboolean is_preview;
+  gboolean done;
+};
+
 typedef struct
 {
   GtkPrintOperationPreview *preview;
@@ -418,8 +535,8 @@ typedef struct
   GtkWindow *parent;
   cairo_surface_t *surface;
   gchar *filename;
-  guint page_nr;
   gboolean wait;
+  PrintPagesData *pages_data;
 } PreviewOp;
 
 static void
@@ -431,16 +548,28 @@ preview_print_idle_done (gpointer data)
   op = GTK_PRINT_OPERATION (pop->preview);
 
   cairo_surface_finish (pop->surface);
-  /* Surface is destroyed in launch_preview */
-  _gtk_print_operation_platform_backend_launch_preview (op,
-                                                       pop->surface,
-                                                       pop->parent,
-                                                       pop->filename);
+
+  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);
 }
@@ -450,35 +579,37 @@ preview_print_idle (gpointer data)
 {
   PreviewOp *pop;
   GtkPrintOperation *op;
-  gboolean retval = TRUE;
-  cairo_t *cr;
   GtkPrintOperationPrivate *priv; 
+  gboolean done = FALSE;
 
   pop = (PreviewOp *) data;
   op = GTK_PRINT_OPERATION (pop->preview);
   priv = op->priv;
 
-
   if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
     {
-      /* TODO: print out sheets not pages and follow ranges */
-      if (pop->page_nr >= op->priv->nr_of_pages)
-        retval = FALSE;
-
-      if (pop->page_nr > 0)
+      if (priv->cancelled)
+       {
+         done = TRUE;
+          _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+       }
+      else if (!pop->pages_data->initialized)
         {
-          cr = gtk_print_context_get_cairo_context (pop->print_context);
-          _gtk_print_operation_platform_backend_preview_end_page (op, pop->surface, cr);
+          pop->pages_data->initialized = TRUE;
+          prepare_data (pop->pages_data);
         }
-
-      if (retval)
+      else
         {
-          gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
-          pop->page_nr++;
+          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 retval;
+  return !done;
 }
 
 static void
@@ -502,7 +633,6 @@ preview_ready (GtkPrintOperationPreview *preview,
                GtkPrintContext          *context,
               PreviewOp                *pop)
 {
-  pop->page_nr = 0;
   pop->print_context = context;
 
   g_object_ref (preview);
@@ -529,6 +659,9 @@ gtk_print_operation_preview_handler (GtkPrintOperation        *op,
   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);
 
@@ -838,8 +971,8 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
    * signal is emitted on the operation. Then you can read out any 
    * information you need from the widgets.
    *
-   * Returns: A custom widget that gets embedded in the print dialog,
-   *          or %NULL
+   * Returns: (transfer none): A custom widget that gets embedded in
+   *          the print dialog, or %NULL
    *
    * Since: 2.10
    */
@@ -899,9 +1032,9 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
    /**
    * GtkPrintOperation::preview:
    * @operation: the #GtkPrintOperation on which the signal was emitted
-   * @preview: the #GtkPrintPreviewOperation for the current operation
+   * @preview: the #GtkPrintOperationPreview for the current operation
    * @context: the #GtkPrintContext that will be used
-   * @parent: the #GtkWindow to use as window parent, or %NULL
+   * @parent: (allow-none): the #GtkWindow to use as window parent, or %NULL
    *
    * Gets emitted when a preview is requested from the native dialog.
    *
@@ -1100,7 +1233,7 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
                                                      P_("Unit"),
                                                      P_("The unit in which distances can be measured in the context"),
                                                      GTK_TYPE_UNIT,
-                                                     GTK_UNIT_PIXEL,
+                                                     GTK_UNIT_NONE,
                                                      GTK_PARAM_READWRITE));
   
   
@@ -1251,7 +1384,7 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
                                   PROP_HAS_SELECTION,
                                   g_param_spec_boolean ("has-selection",
                                                         P_("Has Selection"),
-                                                        P_("TRUE if a selecion exists."),
+                                                        P_("TRUE if a selection exists."),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
 
@@ -1267,7 +1400,7 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
                                   PROP_EMBED_PAGE_SETUP,
                                   g_param_spec_boolean ("embed-page-setup",
                                                         P_("Embed Page Setup"),
-                                                        P_("TRUE if page setup combos are embedded in GtkPrintDialog"),
+                                                        P_("TRUE if page setup combos are embedded in GtkPrintUnixDialog"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
   /**
@@ -1318,8 +1451,8 @@ gtk_print_operation_new (void)
 /**
  * gtk_print_operation_set_default_page_setup:
  * @op: a #GtkPrintOperation
- * @default_page_setup: a #GtkPageSetup, or %NULL
- * 
+ * @default_page_setup: (allow-none): a #GtkPageSetup, or %NULL
+ *
  * Makes @default_page_setup the default page setup for @op.
  *
  * This page setup will be used by gtk_print_operation_run(),
@@ -1358,10 +1491,10 @@ gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
  * gtk_print_operation_get_default_page_setup:
  * @op: a #GtkPrintOperation
  *
- * Returns the default page setup, see 
+ * Returns the default page setup, see
  * gtk_print_operation_set_default_page_setup().
  *
- * Returns: the default page setup 
+ * Returns: (transfer none): the default page setup
  *
  * Since: 2.10
  */
@@ -1377,8 +1510,8 @@ gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
 /**
  * gtk_print_operation_set_print_settings:
  * @op: a #GtkPrintOperation
- * @print_settings: #GtkPrintSettings, or %NULL
- * 
+ * @print_settings: (allow-none): #GtkPrintSettings
+ *
  * Sets the print settings for @op. This is typically used to
  * re-establish print settings from a previous print operation,
  * see gtk_print_operation_run().
@@ -1414,15 +1547,15 @@ gtk_print_operation_set_print_settings (GtkPrintOperation *op,
 /**
  * gtk_print_operation_get_print_settings:
  * @op: a #GtkPrintOperation
- * 
- * Returns the current print settings. 
  *
- * Note that the return value is %NULL until either 
- * gtk_print_operation_set_print_settings() or 
+ * Returns the current print settings.
+ *
+ * Note that the return value is %NULL until either
+ * gtk_print_operation_set_print_settings() or
  * gtk_print_operation_run() have been called.
- * 
- * Return value: the current print settings of @op.
- * 
+ *
+ * Return value: (transfer none): the current print settings of @op.
+ *
  * Since: 2.10
  **/
 GtkPrintSettings *
@@ -1709,7 +1842,7 @@ gtk_print_operation_get_status (GtkPrintOperation *op)
  *
  * Since: 2.10
  **/
-G_CONST_RETURN gchar *
+const gchar *
 gtk_print_operation_get_status_string (GtkPrintOperation *op)
 {
   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
@@ -1811,7 +1944,7 @@ gtk_print_operation_set_allow_async (GtkPrintOperation  *op,
 /**
  * gtk_print_operation_set_custom_tab_label:
  * @op: a #GtkPrintOperation
- * @label: the label to use, or %NULL to use the default label
+ * @label: (allow-none): the label to use, or %NULL to use the default label
  *
  * Sets the label for the tab holding custom widgets.
  *
@@ -1837,7 +1970,7 @@ gtk_print_operation_set_custom_tab_label (GtkPrintOperation  *op,
 /**
  * gtk_print_operation_set_export_filename:
  * @op: a #GtkPrintOperation
- * @filename: the filename for the exported file
+ * @filename: (type filename): the filename for the exported file
  * 
  * Sets up the #GtkPrintOperation to generate a file instead
  * of showing the print dialog. The indended use of this function
@@ -1917,14 +2050,11 @@ pdf_start_page (GtkPrintOperation *op,
                GtkPrintContext   *print_context,
                GtkPageSetup      *page_setup)
 {
-  GtkPaperSize *paper_size;
   cairo_surface_t *surface = op->priv->platform_data;
   gdouble w, h;
 
-  paper_size = gtk_page_setup_get_paper_size (page_setup);
-
-  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
-  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
+  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);
 }
@@ -2013,7 +2143,7 @@ run_pdf (GtkPrintOperation  *op,
   priv->manual_reverse = FALSE;
   priv->manual_page_set = GTK_PAGE_SET_ALL;
   priv->manual_scale = 1.0;
-  priv->manual_orientation = TRUE;
+  priv->manual_orientation = FALSE;
   priv->manual_number_up = 1;
   priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
   
@@ -2026,30 +2156,6 @@ run_pdf (GtkPrintOperation  *op,
   return GTK_PRINT_OPERATION_RESULT_APPLY; 
 }
 
-typedef struct
-{
-  GtkPrintOperation *op;
-  gint uncollated_copies;
-  gint collated_copies;
-  gint uncollated, collated, total;
-
-  gint range, num_ranges;
-  GtkPageRange *ranges;
-  GtkPageRange one_range;
-
-  gint page;
-  gint sheet;
-  gint first_position, last_position;
-  gint first_sheet;
-  gint num_of_sheets;
-  gint *pages;
-
-  GtkWidget *progress;
-  gboolean initialized;
-  gboolean is_preview;
-  gboolean done;
-} PrintPagesData;
 
 static void
 clamp_page_ranges (PrintPagesData *data)
@@ -2097,6 +2203,12 @@ increment_page_sequence (PrintPagesData *data)
   GtkPrintOperationPrivate *priv = data->op->priv;
   gint 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)))
@@ -2121,7 +2233,8 @@ increment_page_sequence (PrintPagesData *data)
         inc = 1;
 
       /* changing sheet */
-      if ((priv->page_position + 1) % priv->manual_number_up == 0 ||
+      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)
         {
@@ -2202,10 +2315,18 @@ print_pages_idle_done (gpointer user_data)
     g_main_loop_quit (priv->rloop);
 
   if (!data->is_preview)
-    g_signal_emit (data->op, signals[DONE], 0,
-                  priv->cancelled ?
-                  GTK_PRINT_OPERATION_RESULT_CANCEL :
-                  GTK_PRINT_OPERATION_RESULT_APPLY);
+    {
+      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);
@@ -2230,7 +2351,7 @@ update_progress (PrintPagesData *data)
            text = g_strdup (_("Preparing"));
        }
       else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
-       text = g_strdup_printf (_("Printing %d"), data->total - 1);
+       text = g_strdup_printf (_("Printing %d"), data->total);
       
       if (text)
        {
@@ -2265,7 +2386,7 @@ gtk_print_operation_set_defer_drawing (GtkPrintOperation *op)
 /**
  * gtk_print_operation_set_embed_page_setup:
  * @op: a #GtkPrintOperation
- * @embed: %TRUE to embed page setup selection in the #GtkPrintDialog
+ * @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.
@@ -2294,7 +2415,7 @@ gtk_print_operation_set_embed_page_setup (GtkPrintOperation  *op,
  * gtk_print_operation_get_embed_page_setup:
  * @op: a #GtkPrintOperation
  *
- * Gets the value of #GtkPrintOperation::embed-page-setup property.
+ * Gets the value of #GtkPrintOperation:embed-page-setup property.
  * 
  * Returns: whether page setup selection combos are embedded
  *
@@ -2374,6 +2495,8 @@ common_render_page (GtkPrintOperation *op,
   
   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)
     {
@@ -2490,6 +2613,10 @@ common_render_page (GtkPrintOperation *op,
             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)
@@ -2573,27 +2700,27 @@ prepare_data (PrintPagesData *data)
 
   priv = data->op->priv;
 
+  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);
+      _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);
 
-      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;
-        }
-
       return;
     }
 
@@ -2660,14 +2787,19 @@ prepare_data (PrintPagesData *data)
         counter++;
       }
 
-  data->total = 0;
+  data->total = -1;
   data->collated = 0;
   data->uncollated = 0;
 
-  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;
+  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 / priv->manual_number_up + 1;
+    data->num_of_sheets = priv->nr_of_pages_to_print;
 
   if (priv->manual_reverse)
     {
@@ -2758,11 +2890,10 @@ print_pages_idle (gpointer user_data)
           goto out;
         }
 
+      increment_page_sequence (data);
+
       if (!data->done)
-        {
-         common_render_page (data->op, data->page);
-         increment_page_sequence (data);
-        }
+        common_render_page (data->op, data->page);
       else
         done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
 
@@ -2820,8 +2951,19 @@ print_pages (GtkPrintOperation       *op,
  
   if (!do_print) 
     {
+      GtkPrintOperationResult tmp_result;
+
       _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
-      g_signal_emit (op, signals[DONE], 0, result);
+
+      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;
   }
   
@@ -2873,8 +3015,9 @@ print_pages (GtkPrintOperation       *op,
           gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
                                                     _("The most probable reason is that a temporary file could not be created."));
 
-          if (parent && parent->group)
-            gtk_window_group_add_window (parent->group, GTK_WINDOW (error_dialog));
+          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_widget_destroy), NULL);
@@ -2901,12 +3044,12 @@ print_pages (GtkPrintOperation       *op,
                                                              &priv->num_page_ranges);
       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 = TRUE;
-      priv->manual_number_up = 1;
-      priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+      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 = gdk_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE + 10,
@@ -2920,9 +3063,9 @@ print_pages (GtkPrintOperation       *op,
       priv->rloop = g_main_loop_new (NULL, FALSE);
 
       g_object_ref (op);
-      GDK_THREADS_LEAVE ();
+      gdk_threads_leave ();
       g_main_loop_run (priv->rloop);
-      GDK_THREADS_ENTER ();
+      gdk_threads_enter ();
       
       g_main_loop_unref (priv->rloop);
       priv->rloop = NULL;
@@ -2958,9 +3101,9 @@ gtk_print_operation_get_error (GtkPrintOperation  *op,
  * gtk_print_operation_run:
  * @op: a #GtkPrintOperation
  * @action: the action to start
- * @parent: Transient parent of the dialog, or %NULL
- * @error: Return location for errors, or %NULL
- * 
+ * @parent: (allow-none): Transient parent of the dialog
+ * @error: (allow-none): Return location for errors, or %NULL
+ *
  * Runs the print operation, by first letting the user modify
  * print settings in the print dialog, and then print the document.
  *
@@ -3098,8 +3241,13 @@ gtk_print_operation_run (GtkPrintOperation        *op,
     print_pages (op, parent, do_print, result);
 
   if (priv->error && error)
-    *error = g_error_copy (priv->error);
-  
+    {
+      *error = g_error_copy (priv->error);
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+    }
+  else if (priv->cancelled)
+    result = GTK_PRINT_OPERATION_RESULT_CANCEL;
   return result;
 }
 
@@ -3154,7 +3302,7 @@ gtk_print_operation_set_support_selection (GtkPrintOperation  *op,
  * gtk_print_operation_get_support_selection:
  * @op: a #GtkPrintOperation
  *
- * Gets the value of #GtkPrintOperation::support-selection property.
+ * Gets the value of #GtkPrintOperation:support-selection property.
  * 
  * Returns: whether the application supports print of selection
  *
@@ -3203,7 +3351,7 @@ gtk_print_operation_set_has_selection (GtkPrintOperation  *op,
  * gtk_print_operation_get_has_selection:
  * @op: a #GtkPrintOperation
  *
- * Gets the value of #GtkPrintOperation::has-selection property.
+ * Gets the value of #GtkPrintOperation:has-selection property.
  * 
  * Returns: whether there is a selection
  *
@@ -3238,10 +3386,7 @@ gtk_print_operation_get_has_selection (GtkPrintOperation *op)
 gint
 gtk_print_operation_get_n_pages_to_print (GtkPrintOperation *op)
 {
-  g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
+  g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), -1);
 
   return op->priv->nr_of_pages_to_print;
 }
-
-#define __GTK_PRINT_OPERATION_C__
-#include "gtkaliasdef.c"