changeset 2830:5d88a8dfa364

Fix #160: Replace print dialog by standard GTK dialog https://github.com/BestImageViewer/geeqie/issues/160 Does not include proof print.
author Colin Clark <colin.clark@cclark.uk>
date Thu, 20 Sep 2018 19:29:39 +0100
parents 7e126fa60a5f
children 29231f01f36c ff9bd38a7a44 f5ba362b3808 6b2afeae4d23
files src/options.c src/options.h src/print.c src/rcfile.c
diffstat 4 files changed, 375 insertions(+), 3284 deletions(-) [+]
line wrap: on
line diff
--- a/src/options.c	Fri Sep 07 19:09:43 2018 +0100
+++ b/src/options.c	Thu Sep 20 19:29:39 2018 +0100
@@ -194,6 +194,10 @@
 	options->read_metadata_in_idle = FALSE;
 	options->star_rating.star = STAR_RATING_STAR;
 	options->star_rating.rejected = STAR_RATING_REJECTED;
+
+	options->printer.font = g_strdup("Serif 10");
+	options->printer.text_fields = 1;
+
 	return options;
 }
 
--- a/src/options.h	Fri Sep 07 19:09:43 2018 +0100
+++ b/src/options.h	Thu Sep 20 19:29:39 2018 +0100
@@ -301,6 +301,12 @@
 		gunichar rejected;
 	} star_rating;
 
+	/* Printer */
+	struct {
+		gchar *font;
+		gint text_fields;
+	} printer;
+
 	gboolean read_metadata_in_idle;
 };
 
--- a/src/print.c	Fri Sep 07 19:09:43 2018 +0100
+++ b/src/print.c	Thu Sep 20 19:29:39 2018 +0100
@@ -1,8 +1,7 @@
 /*
- * Copyright (C) 2004 John Ellis
- * Copyright (C) 2008 - 2016 The Geeqie Team
+ * Copyright (C) 2018 The Geeqie Team
  *
- * Author: John Ellis
+ * Author: Colin Clark
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,169 +22,15 @@
 #include "print.h"
 
 #include "filedata.h"
-#include "filefilter.h"
-#include "image.h"
 #include "image-load.h"
-#include "pixbuf_util.h"
-#include "thumb.h"
-#include "utilops.h"
-#include "ui_bookmark.h"
-#include "ui_menu.h"
 #include "ui_misc.h"
-#include "ui_utildlg.h"
 #include "ui_fileops.h"
-#include "ui_spinner.h"
-#include "ui_tabcomp.h"
-
-#include <locale.h>
-#include <signal.h>
-#include <glib/gprintf.h>
-
-#define PRINT_LPR_COMMAND "lpr"
-#define PRINT_LPR_CUSTOM  "lpr -P %s"
-#define PRINT_LPR_QUERY   "lpstat -p"
-
-#define PRINT_DLG_WIDTH 600
-#define PRINT_DLG_HEIGHT 400
-
-#define PRINT_DLG_PREVIEW_WIDTH 270
-#define PRINT_DLG_PREVIEW_HEIGHT -1
-
-/* these are in point units */
-#define PRINT_MIN_WIDTH 100
-#define PRINT_MIN_HEIGHT 100
-#define PRINT_MAX_WIDTH 4000
-#define PRINT_MAX_HEIGHT 4000
-
-#define PRINT_MARGIN_DEFAULT 36
-
-#define PRINT_PROOF_MIN_SIZE 8
-#define PRINT_PROOF_MAX_SIZE 720
-#define PRINT_PROOF_DEFAULT_SIZE 144
-#define PRINT_PROOF_MARGIN 5
-
-/* default page size */
-#define PAGE_LAYOUT_WIDTH 850
-#define PAGE_LAYOUT_HEIGHT 1100
-
-/* preview uses 1 pixel = PRINT_PREVIEW_SCALE points */
-#define PRINT_PREVIEW_SCALE 4
-
-/* default dpi to use for printing ps image data */
-#define PRINT_PS_DPI_DEFAULT 300.0
-#define PRINT_PS_DPI_MIN 150.0
-/* method to use when scaling down image data */
-#define PRINT_PS_MAX_INTERP GDK_INTERP_BILINEAR
-/* color to use as mask when printing transparent images */
-#define PRINT_PS_MASK_R 255
-#define PRINT_PS_MASK_G 255
-#define PRINT_PS_MASK_B 255
-
-/* padding between objects */
-#define PRINT_TEXT_PADDING 3.0
-
-/* locale for postscript portability */
-#define POSTSCRIPT_LOCALE "C"
-
-
-/* group and keys for saving prefs */
-#define PRINT_PREF_GROUP	"print_settings"
-
-#define PRINT_PREF_SAVE		"save_settings"
-
-#define PRINT_PREF_OUTPUT	"output"
-#define PRINT_PREF_FORMAT	"format"
-#define PRINT_PREF_DPI		"dpi"
-#define PRINT_PREF_UNITS	"units"
-#define PRINT_PREF_SIZE		"size"
-#define PRINT_PREF_ORIENTATION	"orientation"
 
-#define PRINT_PREF_CUSTOM_WIDTH		"custom_width"
-#define PRINT_PREF_CUSTOM_HEIGHT	"custom_height"
-#define PRINT_PREF_MARGIN_LEFT		"margin_left"
-#define PRINT_PREF_MARGIN_RIGHT		"margin_right"
-#define PRINT_PREF_MARGIN_TOP		"margin_top"
-#define PRINT_PREF_MARGIN_BOTTOM	"margin_bottom"
-#define PRINT_PREF_PROOF_WIDTH		"proof_width"
-#define PRINT_PREF_PROOF_HEIGHT		"proof_height"
-
-#define PRINT_PREF_PRINTERC	"custom_printer"
-
-#define PRINT_PREF_TEXT			"text"
-#define PRINT_PREF_TEXTSIZE		"textsize"
-#define PRINT_PREF_TEXTCOLOR_R		"textcolor_r"
-#define PRINT_PREF_TEXTCOLOR_G		"textcolor_g"
-#define PRINT_PREF_TEXTCOLOR_B		"textcolor_b"
-
-#define PRINT_PREF_SOURCE		"source"
-#define PRINT_PREF_LAYOUT		"layout"
-
-#define PRINT_PREF_IMAGE_SCALE		"image_scale"
-
-typedef enum {
-	PRINT_SOURCE_IMAGE = 0,
-	PRINT_SOURCE_SELECTION,
-	PRINT_SOURCE_ALL,
-	PRINT_SOURCE_COUNT
-} PrintSource;
-
-const gchar *print_source_text[] = {
-	N_("Image"),
-	N_("Selection"),
-	N_("All"),
-	NULL
-};
-
-typedef enum {
-	PRINT_LAYOUT_IMAGE = 0,
-	PRINT_LAYOUT_PROOF,
-	PRINT_LAYOUT_COUNT
-} PrintLayout;
+#define PRINT_SETTINGS "print_settings" // filename save printer settings
+#define PAGE_SETUP "page_setup" // filename save page setup
 
-const gchar *print_layout_text[] = {
-	N_("One image per page"),
-	N_("Proof sheet"),
-	NULL
-};
-
-typedef enum {
-	PRINT_OUTPUT_PS_LPR = 0,
-	PRINT_OUTPUT_PS_CUSTOM,
-	PRINT_OUTPUT_PS_FILE,
-	PRINT_OUTPUT_RGB_FILE,
-	PRINT_OUTPUT_COUNT
-} PrintOutput;
-
-const gchar *print_output_text[] = {
-	N_("Default printer"),
-	N_("Custom printer"),
-	N_("PostScript file"),
-	N_("Image file"),
-	NULL,
-	NULL
-};
-
-typedef enum {
-	PRINT_FILE_JPG_LOW = 0,
-	PRINT_FILE_JPG_NORMAL,
-	PRINT_FILE_JPG_HIGH,
-	PRINT_FILE_PNG,
-	PRINT_FILE_COUNT
-} PrintFileFormat;
-
-const gchar *print_file_format_text[] = {
-	N_("jpeg, low quality"),
-	N_("jpeg, normal quality"),
-	N_("jpeg, high quality"),
-	"png",
-	NULL
-};
-
-typedef enum {
-	RENDER_FORMAT_PREVIEW,
-	RENDER_FORMAT_RGB,
-	RENDER_FORMAT_PS
-} RenderFormat;
+/* method to use when scaling down image data */
+#define PRINT_MAX_INTERP GDK_INTERP_HYPER
 
 typedef enum {
 	TEXT_INFO_FILENAME = 1 << 0,
@@ -195,1960 +40,51 @@
 	TEXT_INFO_FILEPATH = 1 << 4
 } TextInfo;
 
-typedef enum {
-	PAPER_UNIT_POINTS = 0,
-	PAPER_UNIT_MM,
-	PAPER_UNIT_CM,
-	PAPER_UNIT_INCH,
-	PAPER_UNIT_PICAS,
-	PAPER_UNIT_COUNT
-} PaperUnits;
-
-typedef enum {
-	PAPER_ORIENTATION_PORTRAIT = 0,
-	PAPER_ORIENTATION_LANDSCAPE,
-	PAPER_ORIENTATION_COUNT
-} PaperOrientation;
-
-
 typedef struct _PrintWindow PrintWindow;
 struct _PrintWindow
 {
-	GenericDialog *dialog;
-
-	FileData *source_fd;
+	GtkWidget *vbox;
 	GList *source_selection;
-	GList *source_list;
-
-	PrintSource source;
-	PrintLayout layout;
-	PrintOutput output;
-
-	gchar *output_path;
-	gchar *output_custom;
-
-	PrintFileFormat output_format;
-
-	gdouble max_dpi;
-
-	GtkWidget *notebook;
-
-	GtkWidget *path_entry;
-	GtkWidget *custom_entry;
-	GtkWidget *path_format_menu;
-	GtkWidget *max_dpi_menu;
-
-	ImageWindow *layout_image;
-	gdouble layout_width;
-	gdouble layout_height;
-
-	guint layout_idle_id; /* event source id */
-
-	gdouble image_scale;
-
-	GtkWidget *image_scale_spin;
-
-	gdouble proof_width;
-	gdouble proof_height;
-	gint proof_columns;
-	gint proof_rows;
-	GList *proof_point;
-	gint proof_position;
-	gint proof_page;
-
-	GtkWidget *proof_group;
-	GtkWidget *proof_width_spin;
-	GtkWidget *proof_height_spin;
-
-	GtkWidget *paper_menu;
-	GtkWidget *paper_width_spin;
-	GtkWidget *paper_height_spin;
-	GtkWidget *paper_units_menu;
-	GtkWidget *paper_orientation_menu;
-
-	GtkWidget *margin_left_spin;
-	GtkWidget *margin_right_spin;
-	GtkWidget *margin_top_spin;
-	GtkWidget *margin_bottom_spin;
-
-	PaperUnits paper_units;
-	gint paper_size;
-	gdouble paper_width;
-	gdouble paper_height;
-	PaperOrientation paper_orientation;
-
-	gdouble margin_left;
-	gdouble margin_right;
-	gdouble margin_top;
-	gdouble margin_bottom;
-
-	GtkWidget *button_back;
-	GtkWidget *button_next;
-	GtkWidget *page_label;
-	GtkWidget *print_button;
-
-	gdouble single_scale;
-	gdouble single_x;
-	gdouble single_y;
-
-	GtkWidget *single_scale_spin;
 
 	TextInfo	text_fields;
-	gint		text_points;
-	guint8		text_r;
-	guint8		text_g;
-	guint8		text_b;
-
-	gint save_settings;
-
-	/* job printing */
-
-	GenericDialog	*job_dialog;
-	GtkWidget	*job_progress;
-	GtkWidget	*job_progress_label;
-
-	RenderFormat	 job_format;
-	PrintOutput	 job_output;
-
-	FILE		*job_file;
-	FILE 		*job_pipe;
-	gchar		*job_path;
-
-	GdkPixbuf	*job_pixbuf;
-
 	gint		 job_page;
 	ImageLoader	*job_loader;
-};
 
-
-static void print_job_throw_error(PrintWindow *pw, const gchar *message);
-static gint print_job_start(PrintWindow *pw, RenderFormat format, PrintOutput output);
-static void print_job_close(PrintWindow *pw, gint error);
-static void print_window_close(PrintWindow *pw);
-
-
-/* misc utils */
-
-static gboolean clip_region(gdouble x1, gdouble y1, gdouble w1, gdouble h1,
-			    gdouble x2, gdouble y2, gdouble w2, gdouble h2,
-			    gdouble *rx, gdouble *ry, gdouble *rw, gdouble *rh)
-{
-	if (x2 + w2 <= x1 || x2 >= x1 + w1 ||
-	    y2 + h2 <= y1 || y2 >= y1 + h1)
-		{
-		return FALSE;
-		}
-
-	*rx = MAX(x1, x2);
-	*rw = MIN((x1 + w1), (x2 + w2)) - *rx;
-
-	*ry = MAX(y1, y2);
-	*rh = MIN((y1 + h1), (y2 + h2)) - *ry;
-
-	return TRUE;
-}
-
-static const gchar *print_output_name(PrintOutput output)
-{
-	if (output >= PRINT_OUTPUT_COUNT) return "";
-
-	return _(print_output_text[output]);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * data
- *-----------------------------------------------------------------------------
- */
-
-
-typedef struct _PaperSize PaperSize;
-struct _PaperSize {
-	gchar *description;
-	gint width;
-	gint height;
-	PaperOrientation orientation;
-};
-
-const gchar *print_paper_units[] = {
-	N_("points"),
-	N_("millimeters"),
-	N_("centimeters"),
-	N_("inches"),
-	N_("picas"),
-	NULL
-};
-
-const gchar *print_paper_orientation[] = {
-	N_("Portrait"),
-	N_("Landscape"),
-	NULL
-};
-
-PaperSize print_paper_sizes[] = {
-	{ N_("Custom"),		360,	720,	PAPER_ORIENTATION_PORTRAIT },
-	{ N_("Letter"),		612,	792,	PAPER_ORIENTATION_PORTRAIT },	/* in 8.5 x 11 */
-	{ N_("Legal"),		612,	1008,	PAPER_ORIENTATION_PORTRAIT },	/* in 8.5 x 14 */
-	{ N_("Executive"),	522,	756,	PAPER_ORIENTATION_PORTRAIT },	/* in 7.25x 10.5 */
-	{ "A0",			2384,	3370,	PAPER_ORIENTATION_PORTRAIT },	/* mm 841 x 1189 */
-	{ "A1",			1684,	2384,	PAPER_ORIENTATION_PORTRAIT },	/* mm 594 x 841 */
-	{ "A2",			1191,	1684,	PAPER_ORIENTATION_PORTRAIT },	/* mm 420 x 594 */
-	{ "A3",			842,	1191,	PAPER_ORIENTATION_PORTRAIT },	/* mm 297 x 420 */
-	{ "A4",			595,	842,	PAPER_ORIENTATION_PORTRAIT },	/* mm 210 x 297 */
-	{ "A5",			420,	595,	PAPER_ORIENTATION_PORTRAIT },	/* mm 148 x 210 */
-	{ "A6",			298,	420,	PAPER_ORIENTATION_PORTRAIT },	/* mm 105 x 148 */
-	{ "B3",			1001,	1417,	PAPER_ORIENTATION_PORTRAIT },	/* mm 353 x 500 */
-	{ "B4",			709,	1001,	PAPER_ORIENTATION_PORTRAIT },	/* mm 250 x 353 */
-	{ "B5",			499,	709,	PAPER_ORIENTATION_PORTRAIT },	/* mm 176 x 250 */
-	{ "B6",			354,	499,	PAPER_ORIENTATION_PORTRAIT },	/* mm 125 x 176 */
-	{ N_("Envelope #10"),	297,	684,	PAPER_ORIENTATION_LANDSCAPE },	/* in 4.125 x 9.5 */
-	{ N_("Envelope #9"),	279,	639,	PAPER_ORIENTATION_LANDSCAPE },	/* in 3.875 x 8.875 */
-	{ N_("Envelope C4"),	649,	918,	PAPER_ORIENTATION_LANDSCAPE },	/* mm 229 x 324 */
-	{ N_("Envelope C5"),	459,	649,	PAPER_ORIENTATION_LANDSCAPE },	/* mm 162 x 229 */
-	{ N_("Envelope C6"),	323,	459,	PAPER_ORIENTATION_LANDSCAPE },	/* mm 114 x 162 */
-	{ N_("Photo 6x4"),	432,	288,	PAPER_ORIENTATION_PORTRAIT },	/* in 6   x 4 */
-	{ N_("Photo 8x10"),	576,	720,	PAPER_ORIENTATION_PORTRAIT },	/* in 8   x 10 */
-	{ N_("Postcard"),	284,	419,	PAPER_ORIENTATION_LANDSCAPE },	/* mm 100 x 148 */
-	{ N_("Tabloid"),	792,	1224,	PAPER_ORIENTATION_PORTRAIT },	/* in 11  x 17 */
-	{ NULL, 0, 0, 0 }
+	GList *print_pixbuf_queue;
+	gboolean job_render_finished;
 };
 
-
-static PaperSize *print_paper_size_nth(gint n)
-{
-	PaperSize *ps = NULL;
-	gint i = 0;
-
-	while (i <= n && print_paper_sizes[i].description)
-		{
-		ps = &print_paper_sizes[i];
-		i++;
-		}
-
-	return ps;
-}
-
-static gint print_paper_size_lookup(gint n, gdouble *width, gdouble *height)
-{
-	PaperSize *ps;
-	gdouble w, h;
-
-	ps = print_paper_size_nth(n);
-	if (!ps) return FALSE;
-
-	if (ps->orientation == PAPER_ORIENTATION_PORTRAIT)
-		{
-		w = ps->width;
-		h = ps->height;
-		}
-	else
-		{
-		h = ps->width;
-		w = ps->height;
-		}
-
-	if (width) *width = w;
-	if (height) *height = h;
-
-	return TRUE;
-}
-
-static gdouble print_paper_size_convert_units(gdouble value, PaperUnits src, PaperUnits dst)
-{
-	gdouble ret;
-
-	if (src == dst) return value;
-
-	switch (src)
-		{
-		case PAPER_UNIT_MM:
-			ret = value / 25.4 * 72.0;
-			break;
-		case PAPER_UNIT_CM:
-			ret = value / 2.54 * 72.0;
-			break;
-		case PAPER_UNIT_INCH:
-			ret = value * 72.0;
-			break;
-		case PAPER_UNIT_PICAS:
-			ret = value * 12.0;
-			break;
-		case PAPER_UNIT_POINTS:
-		default:
-			ret = value;
-			break;
-		}
-
-	switch (dst)
-		{
-		case PAPER_UNIT_MM:
-			ret = ret / 72.0 * 25.4;
-			break;
-		case PAPER_UNIT_CM:
-			ret = ret / 72.0 * 2.54;
-			break;
-		case PAPER_UNIT_INCH:
-			ret = ret / 72.0;
-			break;
-		case PAPER_UNIT_PICAS:
-			ret = ret / 12.0;
-			break;
-		case PAPER_UNIT_POINTS:
-		default:
-			break;
-		}
-
-	return ret;
-}
-
-static PaperUnits paper_unit_default(void)
-{
-	const gchar *result;
-#if 0
-	/* this is not used because it is not even slightly portable */
-	#include <langinfo.h>
-
-	result = nl_langinfo(_NL_MEASUREMENT_MEASUREMENT);
-	if (result[0] == '2') return PAPER_UNIT_INCH;
-#endif
-
-#ifdef LC_MEASUREMENT
-	result = setlocale(LC_MEASUREMENT, NULL);
-#else
-	result = setlocale(LC_ALL, NULL);
-#endif
-	if (result &&
-	    (strstr(result, "_US") || strstr(result, "_PR")) )
-		{
-		return PAPER_UNIT_INCH;
-		}
-
-	return PAPER_UNIT_CM;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * the layout window
- *-----------------------------------------------------------------------------
- */
-
-static gint print_layout_page_count(PrintWindow *pw);
-
-
-static gint print_preview_unit(gdouble points)
-{
-	return (gint)(points / PRINT_PREVIEW_SCALE);
-}
-
-static void print_proof_size(PrintWindow *pw, gdouble *width, gdouble *height)
-{
-	if (width) *width = pw->proof_width + PRINT_PROOF_MARGIN * 2;
-	if (height)
-		{
-		gdouble h;
-
-		h = pw->proof_height + PRINT_PROOF_MARGIN * 2;
-		if (pw->text_fields != 0) h += PRINT_TEXT_PADDING;
-		if (pw->text_fields & TEXT_INFO_FILENAME) h+= (gdouble)pw->text_points * 1.25;
-		if (pw->text_fields & TEXT_INFO_DIMENSIONS) h+= (gdouble)pw->text_points * 1.25;
-		if (pw->text_fields & TEXT_INFO_FILEDATE) h+= (gdouble)pw->text_points * 1.25;
-		if (pw->text_fields & TEXT_INFO_FILESIZE) h+= (gdouble)pw->text_points * 1.25;
-		*height = h;
-		}
-}
-
-static void print_window_layout_status(PrintWindow *pw)
-{
-	gint total;
-	gchar *buf;
-
-	total = print_layout_page_count(pw);
-	pw->proof_page = CLAMP(pw->proof_page, 0, total - 1);
-
-	buf = g_strdup_printf(_("page %d of %d"), pw->proof_page + 1, (total > 0) ? total : 1);
-	gtk_label_set_text(GTK_LABEL(pw->page_label), buf);
-	g_free(buf);
-
-	gtk_widget_set_sensitive(pw->page_label, (total > 0));
-
-	gtk_widget_set_sensitive(pw->button_back, (pw->proof_page > 0));
-	gtk_widget_set_sensitive(pw->button_next, (pw->proof_page < total - 1));
-
-	gtk_widget_set_sensitive(pw->print_button, total > 0);
-}
-
-static void print_window_layout_render_stop(PrintWindow *pw)
-{
-	if (pw->layout_idle_id)
-		{
-		g_source_remove(pw->layout_idle_id);
-		pw->layout_idle_id = 0;
-		}
-}
-
-static gboolean print_window_layout_render_idle(gpointer data)
-{
-	PrintWindow *pw = data;
-
-	print_job_close(pw, FALSE);
-	print_job_start(pw, RENDER_FORMAT_PREVIEW, 0);
-
-	pw->layout_idle_id = 0;
-	return FALSE;
-}
-
-static void print_window_layout_render(PrintWindow *pw)
-{
-	gdouble proof_w, proof_h;
-
-	print_proof_size(pw, &proof_w, &proof_h);
-	pw->proof_columns = (pw->layout_width - pw->margin_left - pw->margin_right) / proof_w;
-	pw->proof_rows = (pw->layout_height - pw->margin_top - pw->margin_bottom) / proof_h;
-
-	print_window_layout_status(pw);
-
-	if (!pw->layout_idle_id)
-		{
-		pw->layout_idle_id = g_idle_add(print_window_layout_render_idle, pw);
-		}
-}
-
-static void print_window_layout_size(PrintWindow *pw)
-{
-	GdkPixbuf *pixbuf;
-	gdouble width;
-	gdouble height;
-	gint sw, sh;
-
-	if (!pw->layout_image) return;
-
-	if (pw->paper_orientation == PAPER_ORIENTATION_LANDSCAPE)
-		{
-		width = pw->paper_height;
-		height = pw->paper_width;
-		}
-	else
-		{
-		width = pw->paper_width;
-		height = pw->paper_height;
-		}
-
-	pw->layout_width = width;
-	pw->layout_height = height;
-
-	sw = print_preview_unit(width);
-	sh = print_preview_unit(height);
-	pixbuf = image_get_pixbuf(pw->layout_image);
-	if (!pixbuf ||
-	    gdk_pixbuf_get_width(pixbuf) != sw ||
-	    gdk_pixbuf_get_height(pixbuf) != sh)
-		{
-		pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, sw, sh);
-		image_change_pixbuf(pw->layout_image, pixbuf, 0.0, FALSE);
-		g_object_unref(pixbuf);
-		}
-
-	print_window_layout_render(pw);
-	print_window_layout_status(pw);
-}
-
 static gint print_layout_page_count(PrintWindow *pw)
 {
 	gint images;
-	gint images_per_page;
-	gint pages;
 
-	if (pw->layout_width - pw->margin_left - pw->margin_right <= 0.0 ||
-	    pw->layout_height - pw->margin_top - pw->margin_bottom <= 0.0)
-		{
-		return 0;
-		}
-
-	switch (pw->source)
-		{
-		case PRINT_SOURCE_ALL:
-			images = g_list_length(pw->source_list);
-			break;
-		case PRINT_SOURCE_SELECTION:
-			images = g_list_length(pw->source_selection);
-			break;
-		case PRINT_SOURCE_IMAGE:
-		default:
-			images = (pw->source_fd) ? 1 : 0;
-			break;
-		}
-
-	switch (pw->layout)
-		{
-		case PRINT_LAYOUT_PROOF:
-			images_per_page = pw->proof_columns * pw->proof_rows;
-			break;
-		case PRINT_LAYOUT_IMAGE:
-		default:
-			images_per_page = 1;
-			break;
-		}
-
-	if (images < 1 || images_per_page < 1) return 0;
-
-	pages = images / images_per_page;
-	if (pages * images_per_page < images) pages++;
-
-	return pages;
-}
-
-static void print_layout_page_step(PrintWindow *pw, gint step)
-{
-	gint max;
-	gint page;
-
-	max = print_layout_page_count(pw);
-	page = pw->proof_page + step;
-
-	if (page >= max) page = max - 1;
-	if (page < 0) page = 0;
-
-	if (page == pw->proof_page) return;
-
-	pw->proof_page = page;
-	print_window_layout_size(pw);
-}
-
-static void print_layout_page_back_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	print_layout_page_step(pw, -1);
-}
-
-static void print_layout_page_next_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	print_layout_page_step(pw, 1);
-}
-
-static void print_layout_zoom_in_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-	image_zoom_adjust(pw->layout_image, 0.25);
-}
-
-static void print_layout_zoom_out_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-	image_zoom_adjust(pw->layout_image, -0.25);
-}
-
-static void print_layout_zoom_original_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-	gdouble zoom;
-
-	zoom = image_zoom_get(pw->layout_image);
-	image_zoom_set(pw->layout_image, (zoom == 1.0) ? 0.0 : 1.0);
-}
-
-static GtkWidget *print_window_layout_setup(PrintWindow *pw, GtkWidget *box)
-{
-	GtkWidget *vbox;
-	GtkWidget *hbox;
-	GtkWidget *group;
-	GtkWidget *button;
-
-	vbox = pref_box_new(box, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
-	group = pref_frame_new(vbox, TRUE, _("Preview"), GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
-
-	pw->layout_idle_id = 0;
-
-	pw->layout_image = image_new(FALSE);
-	gtk_widget_set_size_request(pw->layout_image->widget, PRINT_DLG_PREVIEW_WIDTH, PRINT_DLG_PREVIEW_HEIGHT);
-
-	gtk_box_pack_start(GTK_BOX(group), pw->layout_image->widget, TRUE, TRUE, 0);
-	gtk_widget_show(pw->layout_image->widget);
-
-	hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP);
-	pw->button_back = pref_button_new(hbox, GTK_STOCK_GO_BACK, NULL, TRUE,
-					  G_CALLBACK(print_layout_page_back_cb), pw);
-	pw->button_next = pref_button_new(hbox, GTK_STOCK_GO_FORWARD, NULL, TRUE,
-					  G_CALLBACK(print_layout_page_next_cb), pw);
-	pw->page_label = pref_label_new(hbox, "");
-
-	button = pref_button_new(NULL, GTK_STOCK_ZOOM_OUT, NULL, TRUE,
-				 G_CALLBACK(print_layout_zoom_out_cb), pw);
-	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-	gtk_widget_show(button);
-	button = pref_button_new(NULL, GTK_STOCK_ZOOM_IN, NULL, TRUE,
-				 G_CALLBACK(print_layout_zoom_in_cb), pw);
-	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-	gtk_widget_show(button);
-	button = pref_button_new(NULL, GTK_STOCK_ZOOM_100, NULL, TRUE,
-				 G_CALLBACK(print_layout_zoom_original_cb), pw);
-	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-	gtk_widget_show(button);
-
-	print_window_layout_size(pw);
-
-	return vbox;
-}
-
-static void print_window_spin_set(GtkSpinButton *spin, gpointer block_data,
-				  gdouble value, gdouble min, gdouble max,
-				  gdouble step, gdouble page, gint digits)
-{
-	if (block_data) g_signal_handlers_block_matched(G_OBJECT(spin), G_SIGNAL_MATCH_DATA,
-							0, 0, NULL, NULL, block_data);
-	gtk_spin_button_set_digits(spin, digits);
-	gtk_spin_button_set_increments(spin, step, page);
-	gtk_spin_button_set_range(spin, min, max);
-	gtk_spin_button_set_value(spin, value);
-
-	if (block_data) g_signal_handlers_unblock_matched(G_OBJECT(spin), G_SIGNAL_MATCH_DATA,
-							  0, 0, NULL, NULL, block_data);
-}
-
-static void print_window_layout_sync_layout(PrintWindow *pw)
-{
-	gtk_widget_set_sensitive(pw->image_scale_spin, (pw->layout == PRINT_LAYOUT_IMAGE));
-	gtk_widget_set_sensitive(pw->proof_group, (pw->layout == PRINT_LAYOUT_PROOF));
-}
-
-static void print_window_layout_sync_paper(PrintWindow *pw)
-{
-	gdouble width, height;
-	gint digits;
-	gdouble step;
-	gdouble page;
-
-	gtk_widget_set_sensitive(pw->paper_width_spin, (pw->paper_size == 0));
-	gtk_widget_set_sensitive(pw->paper_height_spin, (pw->paper_size == 0));
-
-	width = print_paper_size_convert_units((gdouble)pw->paper_width, PAPER_UNIT_POINTS, pw->paper_units);
-	height = print_paper_size_convert_units((gdouble)pw->paper_height, PAPER_UNIT_POINTS, pw->paper_units);
-
-	switch (pw->paper_units)
-		{
-		case PAPER_UNIT_MM:
-			digits = 1;
-			step = 1.0;
-			page = 10.0;
-			break;
-		case PAPER_UNIT_CM:
-			digits = 2;
-			step = 0.5;
-			page = 1.0;
-			break;
-		case PAPER_UNIT_INCH:
-			digits = 3;
-			step = 0.25;
-			page = 1.0;
-			break;
-		case PAPER_UNIT_PICAS:
-			digits = 2;
-			step = 1.0;
-			page = 6.0;
-			break;
-		case PAPER_UNIT_POINTS:
-		default:
-			digits = 1;
-			step = 1.0;
-			page = 10.0;
-			break;
-		}
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->paper_width_spin), pw, width,
-			      print_paper_size_convert_units(PRINT_MIN_WIDTH, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_MAX_WIDTH, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->paper_height_spin), pw, height,
-			      print_paper_size_convert_units(PRINT_MIN_HEIGHT, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_MAX_HEIGHT, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->margin_left_spin), pw,
-			      print_paper_size_convert_units(pw->margin_left, PAPER_UNIT_POINTS, pw->paper_units),
-			      0.0,
-			      print_paper_size_convert_units(PRINT_MAX_WIDTH, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->margin_right_spin), pw,
-			      print_paper_size_convert_units(pw->margin_right, PAPER_UNIT_POINTS, pw->paper_units),
-			      0.0,
-			      print_paper_size_convert_units(PRINT_MAX_WIDTH, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->margin_top_spin), pw,
-			      print_paper_size_convert_units(pw->margin_top, PAPER_UNIT_POINTS, pw->paper_units),
-			      0.0,
-			      print_paper_size_convert_units(PRINT_MAX_HEIGHT, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->margin_bottom_spin), pw,
-			      print_paper_size_convert_units(pw->margin_bottom, PAPER_UNIT_POINTS, pw->paper_units),
-			      0.0,
-			      print_paper_size_convert_units(PRINT_MAX_HEIGHT, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->proof_width_spin), pw,
-			      print_paper_size_convert_units(pw->proof_width, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_PROOF_MIN_SIZE, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_PROOF_MAX_SIZE, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-
-	print_window_spin_set(GTK_SPIN_BUTTON(pw->proof_height_spin), pw,
-			      print_paper_size_convert_units(pw->proof_height, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_PROOF_MIN_SIZE, PAPER_UNIT_POINTS, pw->paper_units),
-			      print_paper_size_convert_units(PRINT_PROOF_MAX_SIZE, PAPER_UNIT_POINTS, pw->paper_units),
-			      step, page, digits);
-}
-
-static void print_window_layout_set_size(PrintWindow *pw, gdouble width, gdouble height)
-{
-	pw->paper_width = width;
-	pw->paper_height = height;
-
-	print_window_layout_sync_paper(pw);
-
-	print_window_layout_size(pw);
-}
-
-static void print_window_layout_set_orientation(PrintWindow *pw, PaperOrientation o)
-{
-	if (pw->paper_orientation == o) return;
-
-	pw->paper_orientation = o;
-
-	print_window_layout_size(pw);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * list printers
- *-----------------------------------------------------------------------------
- */
-
-static GList *print_window_list_printers(void)
-{
-	FILE *p;
-	GList *list = NULL;
-	gchar buffer[2048];
-
-	p = popen(PRINT_LPR_QUERY, "r");
-	if (!p) return NULL;
-
-	while (fgets(buffer, sizeof(buffer), p) != NULL)
-		{
-		gchar *ptr;
-		gchar *end;
-
-		ptr = buffer;
-		if (strncmp(ptr, "printer ", 8) != 0) continue;
-		if (strstr(ptr, "enabled") == NULL) continue;
-		ptr += 8;
-		end = ptr;
-		while (*end != '\0' && *end != '\n' && *end != ' ' && *end != '\t') end++;
-		*end = '\0';
-		list = g_list_append(list, g_strdup(ptr));
-		DEBUG_1("adding printer: %s", ptr);
-		}
-
-	pclose(p);
-
-	return list;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * print ps
- *-----------------------------------------------------------------------------
- */
-
-typedef struct _PipeError PipeError;
-struct _PipeError {
-	struct sigaction old_action;
-	sig_atomic_t *error;
-};
-
-static sig_atomic_t pipe_handler_error = FALSE;
-static PipeError *pipe_handler_data = NULL;
-
-static void pipe_handler_sigpipe_cb(gint fd)
-{
-	pipe_handler_error = TRUE;
-}
-
-static PipeError *pipe_handler_new(void)
-{
-	struct sigaction new_action;
-	PipeError *pe;
-
-	if (pipe_handler_data)
-		{
-		log_printf("warning SIGPIPE handler already in use\n");
-		return NULL;
-		}
-
-	pe = g_new0(PipeError, 1);
-
-	pipe_handler_error = FALSE;
-	pe->error = &pipe_handler_error;
-
-	new_action.sa_handler = pipe_handler_sigpipe_cb;
-	sigemptyset(&new_action.sa_mask);
-	new_action.sa_flags = 0;
+	images = g_list_length(pw->source_selection);
 
-	/* setup our signal handler */
-	sigaction(SIGPIPE, &new_action, &pe->old_action);
-
-	pipe_handler_data = pe;
-	return pe;
-}
-
-static void pipe_handler_free(PipeError *pe)
-{
-	if (!pe) return;
-	if (pe != pipe_handler_data) log_printf("warning SIGPIPE handler not closing same data\n");
-
-	/* restore the original signal handler */
-	sigaction(SIGPIPE, &pe->old_action, NULL);
-
-	pipe_handler_data = NULL;
-	g_free(pe);
-}
-
-static gboolean pipe_handler_check(PipeError *pe)
-{
-	if (!pe) return FALSE;
-	return !!(*pe->error);
-}
-
-static FILE *print_job_ps_fd(PrintWindow *pw)
-{
-	if (pw->job_file) return pw->job_file;
-	if (pw->job_pipe) return pw->job_pipe;
-	return NULL;
-}
-
-static gboolean print_job_ps_init(PrintWindow *pw)
-{
-	FILE *f;
-	PipeError *pe;
-	const gchar *cmd = NULL;
-	const gchar *path = NULL;
-	gchar *lc_pointer;
-	gboolean ret;
-
-	if (pw->job_file != NULL || pw->job_pipe != NULL) return FALSE;
-
-	switch (pw->job_output)
-		{
-		case PRINT_OUTPUT_PS_LPR:
-			cmd = PRINT_LPR_COMMAND;
-			break;
-		case PRINT_OUTPUT_PS_CUSTOM:
-			cmd = pw->output_custom;
-			break;
-		case PRINT_OUTPUT_PS_FILE:
-			path = pw->output_path;
-			break;
-		default:
-			return FALSE;
-			break;
-		}
-
-	if (cmd)
-		{
-		pw->job_pipe = popen(cmd, "w");
-
-		if (!pw->job_pipe)
-			{
-			gchar *buf;
-
-			buf = g_strdup_printf(_("Unable to open pipe for writing.\n\"%s\""), cmd);
-			print_job_throw_error(pw, buf);
-			g_free(buf);
-
-			return FALSE;
-			}
-		}
-	else if (path)
-		{
-		gchar *pathl;
-
-		if (isfile(path))
-			{
-			gchar *buf;
-
-			buf = g_strdup_printf(_("A file with name %s already exists."), path);
-			print_job_throw_error(pw, buf);
-			g_free(buf);
-
-			return FALSE;
-			}
-
-		pathl = path_from_utf8(path);
-		pw->job_file = fopen(pathl, "w");
-		g_free(pathl);
-
-		if (!pw->job_file)
-			{
-			gchar *buf;
-
-			buf = g_strdup_printf(_("Failure writing to file %s"), path);
-			print_job_throw_error(pw, buf);
-			g_free(buf);
-
-			return FALSE;
-			}
-
-		g_free(pw->job_path);
-		pw->job_path = g_strdup(path);
-		}
-
-	f = print_job_ps_fd(pw);
-	if (!f) return FALSE;
-
-	lc_pointer = g_strdup(setlocale(LC_NUMERIC, NULL));
-	setlocale(LC_NUMERIC, POSTSCRIPT_LOCALE);
-
-	pe = pipe_handler_new();
-
-	/* comments, etc. */
-	g_fprintf(f, "%%!PS-Adobe-3.0\n");
-	g_fprintf(f, "%%%%Creator: %s Version %s\n", GQ_APPNAME, VERSION);
-	g_fprintf(f, "%%%%CreationDate: \n");
-	g_fprintf(f, "%%%%LanguageLevel 2\n");
-	g_fprintf(f, "%%%%DocumentMedia: \n");
-	g_fprintf(f, "%%%%Orientation: %s\n",
-		(pw->paper_orientation == PAPER_ORIENTATION_PORTRAIT) ? "Portrait" : "Landscape");
-	g_fprintf(f, "%%%%BoundingBox: %f %f %f %f\n",
-		0.0, 0.0, pw->paper_width, pw->paper_height);
-	g_fprintf(f, "%%%%Pages: %d\n", print_layout_page_count(pw));
-	g_fprintf(f, "%%%%PageOrder: Ascend\n");
-	g_fprintf(f, "%%%%Title:\n");
-
-	/* setup page size, coordinates (do we really need this?) */
-	/* enabled for 1.0beta2  https://bugzilla.redhat.com/222639 */
-#if 1
-	g_fprintf(f, "<<\n");
-	g_fprintf(f, "/PageSize [%f %f]\n", pw->layout_width, pw->layout_height);
-	g_fprintf(f, "/ImagingBBox [%f %f %f %f]\n", /* l b r t */
-		pw->margin_left, pw->margin_bottom,
-		pw->layout_width - pw->margin_right, pw->layout_height - pw->margin_top);
-	g_fprintf(f, "/Orientation %d\n",
-		(pw->paper_orientation == PAPER_ORIENTATION_PORTRAIT) ? 0 : 1);
-	g_fprintf(f, ">> setpagedevice\n");
-#endif
-
-	ret = !pipe_handler_check(pe);
-	pipe_handler_free(pe);
-
-	if (lc_pointer)
-		{
-		setlocale(LC_NUMERIC, lc_pointer);
-		g_free(lc_pointer);
-		}
-
-	if (!ret) print_job_throw_error(pw, _("SIGPIPE error writing to printer."));
-
-	return ret;
-}
-
-static gboolean print_job_ps_page_new(PrintWindow *pw, gint page)
-{
-	FILE *f;
-	PipeError *pe;
-	gchar *lc_pointer;
-	gboolean ret;
-
-	f= print_job_ps_fd(pw);
-	if (!f) return FALSE;
-
-	lc_pointer = g_strdup(setlocale(LC_NUMERIC, NULL));
-	setlocale(LC_NUMERIC, POSTSCRIPT_LOCALE);
-
-	pe = pipe_handler_new();
+	if (images < 1 ) return 0;
 
-	g_fprintf(f, "%%%% page %d\n", page + 1);
-
-	if (pw->paper_orientation == PAPER_ORIENTATION_LANDSCAPE)
-		{
-		g_fprintf(f, "/pagelevel save def\n");
-		g_fprintf(f, "%d 0 translate 90 rotate\n", (gint)pw->layout_height);
-		}
-
-	ret = !pipe_handler_check(pe);
-	pipe_handler_free(pe);
-
-	if (lc_pointer)
-		{
-		setlocale(LC_NUMERIC, lc_pointer);
-		g_free(lc_pointer);
-		}
-
-	if (!ret) print_job_throw_error(pw, _("SIGPIPE error writing to printer."));
-
-	return ret;
-}
-
-static gboolean print_job_ps_page_done(PrintWindow *pw)
-{
-	FILE *f;
-	PipeError *pe;
-	gchar *lc_pointer;
-	gboolean ret;
-
-	f = print_job_ps_fd(pw);
-	if (!f) return FALSE;
-
-	lc_pointer = g_strdup(setlocale(LC_NUMERIC, NULL));
-	setlocale(LC_NUMERIC, POSTSCRIPT_LOCALE);
-
-	pe = pipe_handler_new();
-
-	if (pw->paper_orientation == PAPER_ORIENTATION_LANDSCAPE)
-		{
-		g_fprintf(f, "pagelevel restore\n");
-		}
-
-	g_fprintf(f, "showpage\n");
-
-	ret = !pipe_handler_check(pe);
-	pipe_handler_free(pe);
-
-	if (lc_pointer)
-		{
-		setlocale(LC_NUMERIC, lc_pointer);
-		g_free(lc_pointer);
-		}
-
-	if (!ret) print_job_throw_error(pw, _("SIGPIPE error writing to printer."));
-
-	return ret;
-}
-
-static void print_job_ps_page_image_pixel(FILE *f, guchar *pix)
-{
-	static gchar hex_digits[] = "0123456789abcdef";
-	gchar text[8];
-	gint i;
-
-	for (i = 0; i < 3; i++)
-		{
-		text[i*2] = hex_digits[pix[i] >> 4];
-		text[i*2+1] = hex_digits[pix[i] & 0xf];
-		}
-	text[6] = '\0';
-
-	g_fprintf(f, "%s", text);
-}
-static gboolean print_job_ps_page_image(PrintWindow *pw, GdkPixbuf *pixbuf,
-				        gdouble x, gdouble y, gdouble w, gdouble h,
-				        gdouble offx, gdouble offy)
-{
-	FILE *f;
-	PipeError *pe;
-	gchar *lc_pointer;
-	gint sw, sh;
-	gint bps;
-	gint rowstride;
-	guchar *pix;
-	gint i, j;
-	gint c;
-	guchar *p;
-	guchar bps_buf[3];
-	gboolean ret;
-
-	if (!pixbuf) return TRUE;
-
-	f = print_job_ps_fd(pw);
-	if (!f) return FALSE;
-
-	sw = gdk_pixbuf_get_width(pixbuf);
-	sh = gdk_pixbuf_get_height(pixbuf);
-
-	if (pw->max_dpi >= PRINT_PS_DPI_MIN &&
-	    sw / pw->max_dpi > w / 72.0)
-		{
-		pixbuf = gdk_pixbuf_scale_simple(pixbuf,
-						(gint)(w / 72.0 * pw->max_dpi),
-						(gint)(h / 72.0 * pw->max_dpi),
-						PRINT_PS_MAX_INTERP);
-		sw = gdk_pixbuf_get_width(pixbuf);
-		sh = gdk_pixbuf_get_height(pixbuf);
-		}
-	else
-		{
-		g_object_ref(G_OBJECT(pixbuf));
-		}
-
-	bps = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3;
-	rowstride = gdk_pixbuf_get_rowstride(pixbuf);
-	pix = gdk_pixbuf_get_pixels(pixbuf);
-
-	lc_pointer = g_strdup(setlocale(LC_NUMERIC, NULL));
-	setlocale(LC_NUMERIC, POSTSCRIPT_LOCALE);
-
-	pe = pipe_handler_new();
-
-	g_fprintf(f, "gsave\n");
-	g_fprintf(f, "[%f 0 0 %f %f %f] concat\n", w, h, x, pw->layout_height - h - y);
-	g_fprintf(f, "/buf %d string def\n", sw * 3);
-	g_fprintf(f, "%d %d %d\n", sw, sh, 8);
-	g_fprintf(f, "[%d 0 0 -%d 0 %d]\n", sw, sh, sh);
-	g_fprintf(f, "{ currentfile buf readhexstring pop }\n");
-	g_fprintf(f, "false %d colorimage\n", 3);
-
-	c = 0;
-	for (j = 0; j < sh; j++)
-		{
-		p = pix + j * rowstride;
-		for (i = 0; i < sw; i++)
-			{
-			if (bps == 3)
-				{
-				print_job_ps_page_image_pixel(f, p);
-				}
-			else
-				{
-				bps_buf[0] = (p[0] * p[3] + PRINT_PS_MASK_R * (256 - p[3])) >> 8;
-				bps_buf[1] = (p[1] * p[3] + PRINT_PS_MASK_G * (256 - p[3])) >> 8;
-				bps_buf[2] = (p[2] * p[3] + PRINT_PS_MASK_B * (256 - p[3])) >> 8;
-				print_job_ps_page_image_pixel(f, bps_buf);
-				}
-			p+=bps;
-			c++;
-			if (c > 11)
-				{
-				g_fprintf(f, "\n");
-				c = 0;
-				}
-			}
-		}
-	if (c > 0) g_fprintf(f, "\n");
-	g_fprintf(f, "grestore\n");
-
-	ret = !pipe_handler_check(pe);
-	pipe_handler_free(pe);
-
-	if (lc_pointer)
-		{
-		setlocale(LC_NUMERIC, lc_pointer);
-		g_free(lc_pointer);
-		}
-
-	g_object_unref(G_OBJECT(pixbuf));
-
-	if (!ret) print_job_throw_error(pw, _("SIGPIPE error writing to printer."));
-
-	return ret;
+	return images;
 }
 
-static gdouble convert_pango_dpi(gdouble points);
-
-static gboolean print_job_ps_page_text(PrintWindow *pw, const gchar *text, gdouble point_size,
-				       gdouble x, gdouble y, gdouble width,
-				       guint8 r, guint8 g, guint8 b)
-{
-	PangoLayout *layout;
-	PangoFontDescription *desc;
-	GdkPixbuf *pixbuf;
-	gint lw, lh;
-	gboolean ret;
-	gdouble scale_to_max_dpi = (pw->max_dpi >= PRINT_PS_DPI_MIN) ? pw->max_dpi / 72.0 : 1200.0 / 72.0;
-
-	layout = gtk_widget_create_pango_layout(pw->dialog->dialog, NULL);
-
-	desc = pango_font_description_new();
-	pango_font_description_set_size(desc, convert_pango_dpi(point_size) * PANGO_SCALE * scale_to_max_dpi);
-	pango_layout_set_font_description(layout, desc);
-	pango_font_description_free(desc);
-
-	pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
-	pango_layout_set_text(layout, text, -1);
-
-	pango_layout_get_pixel_size(layout, &lw, &lh);
-	x = x - (gdouble)lw / 2.0 / scale_to_max_dpi;
-
-	pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, lw, lh);
-	gdk_pixbuf_fill(pixbuf, 0xffffffff);
-	pixbuf_draw_layout(pixbuf, layout, pw->dialog->dialog, 0, 0, r, g, b, 255);
-	g_object_unref(G_OBJECT(layout));
-
-	ret = print_job_ps_page_image(pw, pixbuf, x, y,
-				       /* do not allow rescaling of the pixbuf due to rounding errors */
-	                              ((gdouble)lw + 0.01) / scale_to_max_dpi,
-	                              ((gdouble)lh + 0.01) / scale_to_max_dpi,
-	                              0, 0);
-
-	g_object_unref(G_OBJECT(pixbuf));
-
-	return ret;
-}
-
-static gboolean print_job_ps_end(PrintWindow *pw)
-{
-	FILE *f;
-	PipeError *pe;
-	gchar *lc_pointer;
-	gboolean ret;
-
-	f = print_job_ps_fd(pw);
-	if (!f) return FALSE;
-
-	lc_pointer = g_strdup(setlocale(LC_NUMERIC, NULL));
-	setlocale(LC_NUMERIC, POSTSCRIPT_LOCALE);
-
-	pe = pipe_handler_new();
-
-	g_fprintf(f, "%%%%EOF\n");
-
-	ret = !pipe_handler_check(pe);
-	pipe_handler_free(pe);
-
-	if (lc_pointer)
-		{
-		setlocale(LC_NUMERIC, lc_pointer);
-		g_free(lc_pointer);
-		}
-
-	if (!ret) print_job_throw_error(pw, _("SIGPIPE error writing to printer."));
-
-	return ret;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * print rgb
- *-----------------------------------------------------------------------------
- */
-
-static gboolean print_job_rgb_page_new(PrintWindow *pw, gint page)
-{
-	gint total;
-
-	if (pw->job_pixbuf)
-		{
-		pixbuf_set_rect_fill(pw->job_pixbuf, 0, 0,
-				     gdk_pixbuf_get_width(pw->job_pixbuf),
-				     gdk_pixbuf_get_height(pw->job_pixbuf),
-				     255, 255, 255, 255);
-		}
-
-	g_free(pw->job_path);
-	pw->job_path = NULL;
-
-	total = print_layout_page_count(pw);
-
-	if (!pw->output_path ||
-	    page < 0 || page >= total) return FALSE;
-
-	if (total > 1)
-		{
-		const gchar *ext;
-		gchar *base;
-
-		ext = registered_extension_from_path(pw->output_path);
-
-		if (ext)
-			{
-			base = g_strndup(pw->output_path, ext - pw->output_path);
-			}
-		else
-			{
-			base = g_strdup(pw->output_path);
-			ext = "";
-			}
-		pw->job_path = g_strdup_printf("%s_%03d%s", base, page + 1, ext);
-		g_free(base);
-		}
-	else
-		{
-		pw->job_path = g_strdup(pw->output_path);
-		}
-
-	if (isfile(pw->job_path))
-		{
-		gchar *buf;
-
-		buf = g_strdup_printf(_("A file with name %s already exists."), pw->job_path);
-		print_job_throw_error(pw, buf);
-		g_free(buf);
-
-		g_free(pw->job_path);
-		pw->job_path = NULL;
-		}
-
-	return (pw->job_path != NULL);
-}
-
-static gboolean print_job_rgb_page_done(PrintWindow *pw)
-{
-	gchar *pathl;
-	gboolean ret = FALSE;
-
-	if (!pw->job_pixbuf) return FALSE;
-
-	pathl = path_from_utf8(pw->job_path);
-
-	if (pw->output_format == PRINT_FILE_PNG)
-		{
-		ret = pixbuf_to_file_as_png(pw->job_pixbuf, pathl);
-		}
-	else
-		{
-		gint quality = 0;
-
-		switch (pw->output_format)
-			{
-			case PRINT_FILE_JPG_LOW:
-				quality = 65;
-				break;
-			case PRINT_FILE_JPG_NORMAL:
-				quality = 80;
-				break;
-			case PRINT_FILE_JPG_HIGH:
-				quality = 95;
-				break;
-			default:
-				break;
-			}
-
-		if (quality > 0)
-			{
-			ret = pixbuf_to_file_as_jpg(pw->job_pixbuf, pathl, quality);
-			}
-		}
-
-	g_free(pathl);
-
-	if (!ret)
-		{
-		gchar *buf;
-
-		buf = g_strdup_printf(_("Failure writing to file %s"), pw->job_path);
-		print_job_throw_error(pw, buf);
-		g_free(buf);
-		}
-
-	return ret;
-}
-
-static gboolean print_job_rgb_page_image(PrintWindow *pw, GdkPixbuf *pixbuf,
-				         gdouble x, gdouble y, gdouble w, gdouble h,
-				         gdouble offx, gdouble offy)
-{
-	gdouble sw, sh;
-	gdouble dw, dh;
-	gdouble rx, ry, rw, rh;
-
-	if (!pw->job_pixbuf) return FALSE;
-	if (!pixbuf) return TRUE;
-
-	sw = (gdouble)gdk_pixbuf_get_width(pixbuf);
-	sh = (gdouble)gdk_pixbuf_get_height(pixbuf);
-
-	dw = (gdouble)gdk_pixbuf_get_width(pw->job_pixbuf);
-	dh = (gdouble)gdk_pixbuf_get_height(pw->job_pixbuf);
-
-	if (clip_region(x, y, w, h,
-			0.0, 0.0, dw, dh,
-			&rx, &ry, &rw, &rh))
-		{
-		gdk_pixbuf_composite(pixbuf, pw->job_pixbuf, rx, ry, rw, rh,
-				     x + offx, y + offy,
-				     w / sw, h / sh,
-				     (w / sw < 0.01 || h / sh < 0.01) ? GDK_INTERP_NEAREST : GDK_INTERP_BILINEAR, 255);
-		}
-
-	return TRUE;
-}
-
-static gdouble convert_pango_dpi(gdouble points)
-{
-	static gdouble dpi = 0.0;
-
-	if (dpi == 0.0)
-		{
-		GtkSettings *settings;
-		GObjectClass *klass;
-
-		settings = gtk_settings_get_default();
-		klass = G_OBJECT_CLASS(GTK_SETTINGS_GET_CLASS(settings));
-		if (g_object_class_find_property(klass, "gtk-xft-dpi"))
-			{
-			gint int_dpi;
-			g_object_get(settings, "gtk-xft-dpi", &int_dpi, NULL);
-			dpi = (gdouble)int_dpi / PANGO_SCALE;
-			}
-
-		if (dpi < 25.0)
-			{
-			static gboolean warned = FALSE;
-			gdouble fallback_dpi = 96.0;
-
-			if (!warned)
-				{
-				if (dpi == 0.0)
-					{
-					log_printf("pango dpi unknown, assuming %.0f\n", fallback_dpi);
-					}
-				else
-					{
-					log_printf("pango dpi reported as %.0f ignored, assuming %.0f\n", dpi, fallback_dpi);
-					}
-				warned = TRUE;
-				}
-
-			dpi = fallback_dpi;
-			}
-		}
-
-	if (dpi == 0) return points;
-	return points * 72.0 / dpi;
-}
-
-static gboolean print_job_rgb_page_text(PrintWindow *pw, const gchar *text, gdouble point_size,
-				        gdouble x, gdouble y, gdouble width,
-				        guint8 r, guint8 g, guint8 b)
-{
-	PangoLayout *layout;
-	PangoFontDescription *desc;
-	gint lw, lh;
-
-	if (!pw->job_pixbuf) return FALSE;
-
-	layout = gtk_widget_create_pango_layout(pw->dialog->dialog, NULL);
-
-	desc = pango_font_description_new();
-	pango_font_description_set_size(desc, convert_pango_dpi(point_size) * PANGO_SCALE);
-	pango_layout_set_font_description(layout, desc);
-	pango_font_description_free(desc);
-
-	pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
-	pango_layout_set_text(layout, text, -1);
-
-	pango_layout_get_pixel_size(layout, &lw, &lh);
-	x = x - (gdouble)lw / 2.0;
-
-	pixbuf_draw_layout(pw->job_pixbuf, layout, pw->dialog->dialog, x, y, r, g, b, 255);
-	g_object_unref(G_OBJECT(layout));
-
-	return TRUE;
-}
-
-static gboolean print_job_rgb_init(PrintWindow *pw)
-{
-	if (pw->job_pixbuf) g_object_unref(pw->job_pixbuf);
-	pw->job_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
-					(gint)pw->layout_width, (gint)pw->layout_height);
-
-	return print_job_rgb_page_new(pw, pw->job_page);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * print preview
- *-----------------------------------------------------------------------------
- */
-
-static gboolean print_job_preview_page_new(PrintWindow *pw, gint page)
-{
-	GdkPixbuf *pixbuf;
-	gint w, h;
-	gint l, r, t, b;
-
-	pixbuf = pw->job_pixbuf;
-	if (!pixbuf) return FALSE;
-
-	w = print_preview_unit(pw->layout_width);
-	h = print_preview_unit(pw->layout_height);
-	l = print_preview_unit(pw->margin_left);
-	r = print_preview_unit(pw->margin_right);
-	t = print_preview_unit(pw->margin_top);
-	b = print_preview_unit(pw->margin_bottom);
-
-	/* fill background */
-	pixbuf_set_rect_fill(pixbuf, 0, 0, w, h,
-			     255, 255, 255, 255);
-
-	/* draw cm or inch grid */
-	if (TRUE)
-		{
-		gdouble i;
-		gdouble grid;
-		PaperUnits units;
-
-		units = (pw->paper_units == PAPER_UNIT_MM ||
-			 pw->paper_units == PAPER_UNIT_CM) ? PAPER_UNIT_CM : PAPER_UNIT_INCH;
-
-		grid = print_paper_size_convert_units(1.0, units, PAPER_UNIT_POINTS);
-		for (i = grid ; i < pw->layout_width; i += grid)
-			{
-			pixbuf_draw_rect_fill(pixbuf, print_preview_unit(i), 0, 1, h, 0, 0, 0, 16);
-			}
-		for (i = grid; i < pw->layout_height; i += grid)
-			{
-			pixbuf_draw_rect_fill(pixbuf, 0, print_preview_unit(i), w, 1, 0, 0, 0, 16);
-			}
-		}
-
-	/* proof sheet grid */
-	if (pw->layout == PRINT_LAYOUT_PROOF)
-		{
-		gdouble i, j;
-		gdouble proof_w, proof_h;
-		gint uw, uh;
-
-		print_proof_size(pw, &proof_w, &proof_h);
-		uw = print_preview_unit(proof_w + PRINT_PREVIEW_SCALE - 0.1);
-		uh = print_preview_unit(proof_h + PRINT_PREVIEW_SCALE - 0.1);
-
-		for (i = 0; i < pw->proof_columns; i++)
-		    for (j = 0; j < pw->proof_rows; j++)
-			{
-			gint x, y;
-
-			x = pw->margin_left + (pw->layout_width - pw->margin_left - pw->margin_right - (pw->proof_columns * proof_w)) / 2 + i * proof_w;
-			y = pw->margin_top + j * proof_h;
-
-			pixbuf_draw_rect(pixbuf, print_preview_unit(x), print_preview_unit(y), uw, uh,
-					 255, 0, 0, 64, 1, 1, 1, 1);
-			}
-		}
-
-	/* non-printable region (margins) */
-	pixbuf_draw_rect(pixbuf, 0, 0, w, h,
-			 0, 0, 0, 16,
-			 l, r, t, b);
-
-	/* margin lines */
-	pixbuf_draw_rect(pixbuf, l, 0, w - l - r, h,
-			 0, 0, 255, 128,
-			 1, 1, 0, 0);
-	pixbuf_draw_rect(pixbuf, 0, t, w, h - t - b,
-			 0, 0, 255, 128,
-			 0, 0, 1, 1);
-
-	/* border */
-	pixbuf_draw_rect(pixbuf, 0, 0, w, h,
-			 0, 0, 0, 255,
-			 1, 1, 1, 1);
-
-	image_area_changed(pw->layout_image, 0, 0, w, h);
-
-	return TRUE;
-}
-
-static gboolean print_job_preview_page_done(PrintWindow *pw)
-{
-	return TRUE;
-}
-
-static gboolean print_job_preview_page_image(PrintWindow *pw, GdkPixbuf *pixbuf,
-					     gdouble x, gdouble y, gdouble w, gdouble h,
-					     gdouble offx, gdouble offy)
-{
-	gdouble sw, sh;
-	gdouble dw, dh;
-	gdouble rx, ry, rw, rh;
-
-	if (!pw->job_pixbuf) return FALSE;
-	if (!pixbuf) return TRUE;
-
-	sw = (gdouble)gdk_pixbuf_get_width(pixbuf);
-	sh = (gdouble)gdk_pixbuf_get_height(pixbuf);
-
-	dw = (gdouble)gdk_pixbuf_get_width(pw->job_pixbuf);
-	dh = (gdouble)gdk_pixbuf_get_height(pw->job_pixbuf);
-
-	x = print_preview_unit(x);
-	y = print_preview_unit(y);
-	w = print_preview_unit(w);
-	h = print_preview_unit(h);
-	offx = print_preview_unit(offx);
-	offy = print_preview_unit(offy);
-
-	if (clip_region(x, y, w, h,
-			0.0, 0.0, dw, dh,
-			&rx, &ry, &rw, &rh))
-		{
-		gdk_pixbuf_composite(pixbuf, pw->job_pixbuf, rx, ry, rw, rh,
-				     x + offx, y + offy,
-				     w / sw, h / sh,
-				     (w / sw < 0.01 || h / sh < 0.01) ? GDK_INTERP_NEAREST : GDK_INTERP_BILINEAR, 255);
-
-		image_area_changed(pw->layout_image, rx, ry, rw, rh);
-		}
-
-	return TRUE;
-}
-
-static gboolean print_job_preview_page_text(PrintWindow *pw, const gchar *text, gdouble point_size,
-					    gdouble x, gdouble y, gdouble width,
-					    guint8 r, guint8 g, guint8 b)
-{
-	PangoLayout *layout;
-	PangoFontDescription *desc;
-	gint lw, lh;
-	GdkPixbuf *pixbuf;
-
-	if (!pw->job_pixbuf) return FALSE;
-
-	layout = gtk_widget_create_pango_layout(pw->dialog->dialog, NULL);
-
-	desc = pango_font_description_new();
-	pango_font_description_set_size(desc, convert_pango_dpi(point_size) * PANGO_SCALE);
-	pango_layout_set_font_description(layout, desc);
-	pango_font_description_free(desc);
-
-	pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
-	pango_layout_set_text(layout, text, -1);
-
-	pango_layout_get_pixel_size(layout, &lw, &lh);
-	x = x - (gdouble)lw / 2.0;
-
-	pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, lw, lh);
-	pixbuf_set_rect_fill(pixbuf, 0, 0, lw, lh, 0, 0, 0, 0);
-	pixbuf_draw_layout(pixbuf, layout, pw->dialog->dialog, 0, 0, r, g, b, 255);
-	g_object_unref(G_OBJECT(layout));
-
-	print_job_preview_page_image(pw, pixbuf, x, y, (gdouble)lw, (gdouble)lh, 0, 0);
-	g_object_unref(pixbuf);
-
-	return TRUE;
-}
-
-static gboolean print_job_preview_init(PrintWindow *pw)
-{
-	if (pw->job_pixbuf) g_object_unref(pw->job_pixbuf);
-	pw->job_pixbuf = image_get_pixbuf(pw->layout_image);
-	g_object_ref(pw->job_pixbuf);
-
-	return print_job_preview_page_new(pw, pw->job_page);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * wrappers
- *-----------------------------------------------------------------------------
- */
-
-static gboolean print_job_page_new(PrintWindow *pw)
-{
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			return print_job_rgb_page_new(pw, pw->job_page);
-		case RENDER_FORMAT_PS:
-			return print_job_ps_page_new(pw, pw->job_page);
-		case RENDER_FORMAT_PREVIEW:
-			return print_job_preview_page_new(pw, pw->job_page);
-		}
-
-	return FALSE;
-}
-
-static gboolean print_job_page_done(PrintWindow *pw)
-{
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			return print_job_rgb_page_done(pw);
-		case RENDER_FORMAT_PS:
-			return print_job_ps_page_done(pw);
-		case RENDER_FORMAT_PREVIEW:
-			return print_job_preview_page_done(pw);
-		}
-
-	return FALSE;
-}
-
-static gboolean print_job_page_image(PrintWindow *pw, GdkPixbuf *pixbuf,
-				     gdouble x, gdouble y, gdouble w, gdouble h,
-				     gdouble offx, gdouble offy)
-{
-	gboolean success = FALSE;
-
-	if (w <= 0.0 || h <= 0.0) return TRUE;
-
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			success = print_job_rgb_page_image(pw, pixbuf, x, y, w, h, offx, offy);
-			break;
-		case RENDER_FORMAT_PS:
-			success = print_job_ps_page_image(pw, pixbuf, x, y, w, h, offx, offy);
-			break;
-		case RENDER_FORMAT_PREVIEW:
-			success = print_job_preview_page_image(pw, pixbuf, x, y, w, h, offx, offy);
-			break;
-		}
-
-	return success;
-}
-
-static gboolean print_job_page_text(PrintWindow *pw, const gchar *text, gdouble point_size,
-				    gdouble x, gdouble y, gdouble width,
-				    guint8 r, guint8 g, guint8 b)
-{
-	gboolean success = TRUE;
-
-	if (!text) return TRUE;
-
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			success = print_job_rgb_page_text(pw, text, point_size, x, y, width, r, g, b);
-			break;
-		case RENDER_FORMAT_PS:
-			success = print_job_ps_page_text(pw, text, point_size, x, y, width, r, g, b);
-			break;
-		case RENDER_FORMAT_PREVIEW:
-			success = print_job_preview_page_text(pw, text, point_size, x, y, width, r, g, b);
-			break;
-		}
-
-	return success;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * print ?
- *-----------------------------------------------------------------------------
- */
-
 static gboolean print_job_render_image(PrintWindow *pw);
-static gboolean print_job_render_proof(PrintWindow *pw);
-
-
-static void print_job_status(PrintWindow *pw)
-{
-	gdouble value;
-	gint page;
-	gint total;
-	gchar *buf;
-
-	if (!pw->job_progress) return;
-
-	page = pw->job_page;
-	total = print_layout_page_count(pw);
-
-	if (pw->layout == PRINT_LAYOUT_PROOF && pw->proof_point)
-		{
-		GList *start;
-
-		start = g_list_first(pw->proof_point);
-		value = (gdouble)g_list_position(start, pw->proof_point) / g_list_length(start);
-		}
-	else
-		{
-		value = (total > 0) ? (gdouble)page / total : 0.0;
-		}
-
-	buf = g_strdup_printf(_("Page %d"), page + 1);
-	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pw->job_progress), buf);
-	g_free(buf);
-
-	if (pw->job_path && pw->job_progress_label)
-		{
-		gtk_label_set_text(GTK_LABEL(pw->job_progress_label), pw->job_path);
-		}
-
-	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pw->job_progress), value);
-}
-
-static void print_job_throw_error(PrintWindow *pw, const gchar *message)
-{
-	GenericDialog *gd;
-	GtkWidget *parent = NULL;
-	GtkWidget *group;
-	GtkWidget *label;
-	gchar *buf;
-
-	if (gtk_widget_get_visible(pw->dialog->dialog)) parent = pw->dialog->dialog;
-
-	gd = generic_dialog_new(_("Printing error"), "print_warning",
-				parent, TRUE, NULL, NULL);
-	generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, NULL, TRUE);
-
-	buf = g_strdup_printf(_("An error occurred printing to %s."), print_output_name(pw->output));
-	generic_dialog_add_message(gd, GTK_STOCK_DIALOG_ERROR, _("Printing error"), buf, TRUE);
-	g_free(buf);
-
-	group = pref_group_new(gd->vbox, FALSE, _("Details"), GTK_ORIENTATION_VERTICAL);
-	label = pref_label_new(group, message);
-	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
-	gtk_widget_show(gd->dialog);
-}
-
-static void print_job_done(PrintWindow *pw)
-{
-	print_job_close(pw, FALSE);
-}
-
-static gboolean print_job_text_image(PrintWindow *pw, const gchar *path,
-				     gdouble x, gdouble y, gdouble width,
-				     gint sw, gint sh, gint proof)
-{
-	GString *string;
-	gboolean space = FALSE;
-	gboolean newline = FALSE;
-	gboolean ret;
-
-	if (pw->text_fields == 0) return TRUE;
-
-	string = g_string_new("");
-	path = image_loader_get_fd(pw->job_loader)->path;
-
-	if (pw->text_fields & TEXT_INFO_FILENAME)
-		{
-		if (pw->text_fields & TEXT_INFO_FILEPATH)
-			g_string_append(string, path);
-		else
-			g_string_append(string, filename_from_path(path));
-		newline = TRUE;
-		}
-	else if (pw->text_fields & TEXT_INFO_FILEPATH)
-		{
-		gchar *dirname = g_path_get_dirname(path);
-
-		g_string_append_printf(string, "%s%s", dirname, G_DIR_SEPARATOR_S);
-		g_free(dirname);
-		newline = TRUE;
-		}
-	if (pw->text_fields & TEXT_INFO_DIMENSIONS)
-		{
-		if (newline) g_string_append(string, "\n");
-		g_string_append_printf(string, "%d x %d", (gint)sw, (gint)sh);
-		newline = proof;
-		space = !proof;
-		}
-	if (pw->text_fields & TEXT_INFO_FILEDATE)
-		{
-		if (newline)  g_string_append(string, "\n");
-		if (space) g_string_append(string, " - ");
-		g_string_append(string, text_from_time(filetime(image_loader_get_fd(pw->job_loader)->path)));
-		newline = proof;
-		space = !proof;
-		}
-	if (pw->text_fields & TEXT_INFO_FILESIZE)
-		{
-		gchar *size;
-
-		if (newline)  g_string_append(string, "\n");
-		if (space) g_string_append(string, " - ");
-		size = text_from_size_abrev(filesize(image_loader_get_fd(pw->job_loader)->path));
-		g_string_append(string, size);
-		g_free(size);
-		}
-
-	ret = print_job_page_text(pw, string->str, pw->text_points, x, y, width,
-				  pw->text_r, pw->text_g, pw->text_b);
-
-	g_string_free(string, TRUE);
-
-	return ret;
-}
 
 static void print_job_render_image_loader_done(ImageLoader *il, gpointer data)
 {
 	PrintWindow *pw = data;
 	GdkPixbuf *pixbuf;
-	gboolean success = TRUE;
 
 	pixbuf = image_loader_get_pixbuf(il);
-	if (pixbuf)
-		{
-		gdouble sw, sh;
-		gdouble dw, dh;
-		gdouble x, y, w, h;
-		gdouble offx, offy;
 
-		sw = (gdouble)gdk_pixbuf_get_width(pixbuf);
-		sh = (gdouble)gdk_pixbuf_get_height(pixbuf);
-
-		dw = pw->layout_width - pw->margin_left - pw->margin_right;
-		dh = pw->layout_height - pw->margin_top - pw->margin_bottom;
-
-		if (dw / sw < dh / sh)
-			{
-			w = dw;
-			h = dw / sw * sh;
-			}
-		else
-			{
-			h = dh;
-			w = dh / sh *sw;
-			}
-
-		if (pw->image_scale >= 5.0)
-			{
-			w = w * pw->image_scale / 100.0;
-			h = h * pw->image_scale / 100.0;
-			}
-
-		x = pw->margin_left + (dw / 2) - (w / 2);
-		y = pw->margin_top + (dh / 2) - (h / 2);
-
-		offx = offy = 0;
-
-		if (x < 0)
-			{
-			w += x;
-			offx = x;
-			x = 0;
-			}
-		if (x + w >= pw->layout_width) w = pw->layout_width - x;
-
-		if (y < 0)
-			{
-			h += y;
-			offy = y;
-			y = 0;
-			}
-		if (y + h >= pw->layout_height) h = pw->layout_height - y;
-
-		success = (success &&
-			   print_job_page_image(pw, pixbuf, x, y, w, h, offx, offy));
-
-		x = x + w / 2;
-		y = y + h + PRINT_TEXT_PADDING;
-
-		success = (success &&
-			   print_job_text_image(pw, image_loader_get_fd(pw->job_loader)->path, x, y, dw, sw, sh, FALSE));
-		}
+	g_object_ref(pixbuf);
+	pw->print_pixbuf_queue = g_list_append(pw->print_pixbuf_queue, pixbuf);
 
 	image_loader_free(pw->job_loader);
 	pw->job_loader = NULL;
 
-	if (pw->job_format == RENDER_FORMAT_PREVIEW)
-		{
-		print_job_done(pw);
-		return;
-		}
+	pw->job_page++;
 
-	success = (success && print_job_page_done(pw));
-	if (!success)
+	if (!print_job_render_image(pw))
 		{
-		print_job_close(pw, TRUE);
-		return;
-		}
-
-	pw->job_page++;
-	print_job_status(pw);
-
-	if (print_job_render_image(pw))
-		{
-		if (!print_job_page_new(pw)) print_job_close(pw, TRUE);
-		}
-	else
-		{
-		print_job_done(pw);
+		pw->job_render_finished = TRUE;
 		}
 }
 
@@ -2156,27 +92,16 @@
 {
 	FileData *fd = NULL;
 
-	switch (pw->source)
-		{
-		case PRINT_SOURCE_SELECTION:
-			fd = g_list_nth_data(pw->source_selection, pw->job_page);
-			break;
-		case PRINT_SOURCE_ALL:
-			fd = g_list_nth_data(pw->source_list, pw->job_page);
-			break;
-		case PRINT_SOURCE_IMAGE:
-		default:
-			if (pw->job_page == 0) fd = pw->source_fd;
-			break;
-		}
+	fd = g_list_nth_data(pw->source_selection, pw->job_page);
+	if (!fd) return FALSE;
 
 	image_loader_free(pw->job_loader);
 	pw->job_loader = NULL;
 
-	if (!fd) return FALSE;
+	pw->job_loader = image_loader_new(fd);
+	g_signal_connect(G_OBJECT(pw->job_loader), "done",
+						(GCallback)print_job_render_image_loader_done, pw);
 
-	pw->job_loader = image_loader_new(fd);
-	g_signal_connect(G_OBJECT(pw->job_loader), "done", (GCallback)print_job_render_image_loader_done, pw);
 	if (!image_loader_start(pw->job_loader))
 		{
 		image_loader_free(pw->job_loader);
@@ -2186,953 +111,6 @@
 	return TRUE;
 }
 
-static void print_job_render_proof_loader_done(ImageLoader *il, gpointer data)
-{
-	PrintWindow *pw = data;
-	GdkPixbuf *pixbuf;
-	gdouble x, y;
-	gdouble w, h;
-	gdouble proof_w, proof_h;
-	gdouble icon_w, icon_h;
-	gboolean success = TRUE;
-
-	if (pw->proof_columns < 1 || pw->proof_rows < 1)
-		{
-		image_loader_free(pw->job_loader);
-		pw->job_loader = NULL;
-
-		print_job_done(pw);
-
-		return;
-		}
-
-	pixbuf = image_loader_get_pixbuf(il);
-
-	if (options->image.exif_proof_rotate_enable == TRUE) {
-		pixbuf = pixbuf_apply_orientation(pixbuf, il->fd->exif_orientation);
-	}
-
-	w = gdk_pixbuf_get_width(pixbuf);
-	h = gdk_pixbuf_get_height(pixbuf);
-
-	if (pw->proof_width / w < pw->proof_height / h)
-		{
-		icon_w = pw->proof_width;
-		icon_h = pw->proof_width / w * h;
-		}
-	else
-		{
-		icon_h = pw->proof_height;
-		icon_w = pw->proof_height / h * w;
-		}
-
-	y = pw->proof_position / pw->proof_columns;
-	x = pw->proof_position - (y * pw->proof_columns);
-
-	print_proof_size(pw, &proof_w, &proof_h);
-
-	x *= proof_w;
-	y *= proof_h;
-	x += pw->margin_left + (pw->layout_width - pw->margin_left - pw->margin_right - (pw->proof_columns * proof_w)) / 2 + (proof_w - icon_w) / 2;
-	y += pw->margin_top + PRINT_PROOF_MARGIN + (pw->proof_height - icon_h) / 2;
-
-	success = (success &&
-		   print_job_page_image(pw, pixbuf, x, y, icon_w, icon_h, 0, 0));
-
-	x = x + icon_w / 2;
-	y = y + icon_h + (pw->proof_height - icon_h) / 2 + PRINT_TEXT_PADDING;
-
-	success = (success &&
-		   print_job_text_image(pw, image_loader_get_fd(pw->job_loader)->path, x, y, icon_w + PRINT_PROOF_MARGIN * 2, w, h, TRUE));
-
-	if (!success)
-		{
-		print_job_close(pw, TRUE);
-		return;
-		}
-
-	if (pw->proof_point) pw->proof_point = pw->proof_point->next;
-
-	pw->proof_position++;
-	if (pw->proof_position >= pw->proof_columns * pw->proof_rows)
-		{
-		if (pw->job_format == RENDER_FORMAT_PREVIEW)
-			{
-			print_job_done(pw);
-			return;
-			}
-
-		if (!print_job_page_done(pw))
-			{
-			print_job_close(pw, TRUE);
-			return;
-			}
-
-		pw->proof_position = 0;
-		pw->job_page++;
-		if (print_job_render_proof(pw))
-			{
-			if (!print_job_page_new(pw))
-				{
-				print_job_close(pw, TRUE);
-				return;
-				}
-			print_job_status(pw);
-			}
-		else
-			{
-			print_job_done(pw);
-			}
-		}
-	else
-		{
-		if (print_job_render_proof(pw))
-			{
-			print_job_status(pw);
-			}
-		else
-			{
-			if (print_job_page_done(pw))
-				{
-				print_job_done(pw);
-				}
-			else
-				{
-				print_job_close(pw, TRUE);
-				}
-			}
-		}
-}
-
-static gboolean print_job_render_proof(PrintWindow *pw)
-{
-	FileData *fd = NULL;
-
-	if (pw->proof_columns < 1 || pw->proof_rows < 1) return FALSE;
-
-	if (!pw->proof_point && pw->proof_position == 0 && pw->source == PRINT_SOURCE_IMAGE)
-		{
-		fd = pw->source_fd;
-		}
-	else if (pw->proof_point &&
-		 pw->proof_position < pw->proof_columns * pw->proof_rows)
-		{
-		fd = pw->proof_point->data;
-		}
-
-	if (!fd) return FALSE;
-
-	image_loader_free(pw->job_loader);
-	pw->job_loader = image_loader_new(fd);
-	g_signal_connect(G_OBJECT(pw->job_loader), "done", (GCallback)print_job_render_proof_loader_done, pw);
-	if (!image_loader_start(pw->job_loader))
-		{
-		image_loader_free(pw->job_loader);
-		pw->job_loader = NULL;
-		}
-
-	return TRUE;
-}
-
-static void print_job_render(PrintWindow *pw)
-{
-	gdouble proof_w, proof_h;
-	gboolean finished;
-
-	pw->proof_position = 0;
-
-	switch (pw->source)
-		{
-		case PRINT_SOURCE_SELECTION:
-			pw->proof_point = pw->source_selection;
-			break;
-		case PRINT_SOURCE_ALL:
-			pw->proof_point = pw->source_list;
-			break;
-		case PRINT_SOURCE_IMAGE:
-		default:
-			pw->proof_point = NULL;
-			break;
-		}
-
-	print_proof_size(pw, &proof_w, &proof_h);
-	pw->proof_columns = (pw->layout_width - pw->margin_left - pw->margin_right) / proof_w;
-	pw->proof_rows = (pw->layout_height - pw->margin_top - pw->margin_bottom) / proof_h;
-
-	if (pw->job_format == RENDER_FORMAT_PREVIEW)
-		{
-		gint total;
-
-		total = print_layout_page_count(pw);
-		if (pw->job_page < 0 || pw->job_page >= total)
-			{
-			print_job_done(pw);
-			return;
-			}
-
-		if (pw->proof_point && pw->job_page > 0)
-			{
-			pw->proof_point = g_list_nth(pw->proof_point, pw->job_page * pw->proof_columns * pw->proof_rows);
-			}
-		}
-
-	if (!print_job_page_new(pw))
-		{
-		print_job_close(pw, TRUE);
-		return;
-		}
-
-	if (pw->layout == PRINT_LAYOUT_IMAGE)
-		{
-		finished = !print_job_render_image(pw);
-		}
-	else
-		{
-		finished = !print_job_render_proof(pw);
-		}
-
-	if (finished) print_job_done(pw);
-}
-
-static gboolean print_job_init(PrintWindow *pw)
-{
-	gboolean success = FALSE;
-
-	pw->job_page = 0;
-
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			success = print_job_rgb_init(pw);
-			break;
-		case RENDER_FORMAT_PS:
-			success = print_job_ps_init(pw);
-			break;
-		case RENDER_FORMAT_PREVIEW:
-			pw->job_page = pw->proof_page;
-			success = print_job_preview_init(pw);
-			break;
-		}
-
-	return success;
-}
-
-static gboolean print_job_finish(PrintWindow *pw)
-{
-	gboolean success = FALSE;
-
-	switch (pw->job_format)
-		{
-		case RENDER_FORMAT_RGB:
-			success = TRUE;
-			break;
-		case RENDER_FORMAT_PS:
-			print_job_ps_end(pw);
-			break;
-		case RENDER_FORMAT_PREVIEW:
-			success = TRUE;
-			break;
-		}
-
-	return success;
-}
-
-static void print_job_close_file(PrintWindow *pw)
-{
-	if (pw->job_file)
-		{
-		fclose(pw->job_file);
-		pw->job_file = NULL;
-		}
-
-	if (pw->job_pipe)
-		{
-		PipeError *pe;
-
-		pe = pipe_handler_new();
-		pclose(pw->job_pipe);
-		pipe_handler_free(pe);
-
-		pw->job_pipe = NULL;
-		}
-}
-
-static gboolean print_job_close_finish_cb(gpointer data)
-{
-	PrintWindow *pw = data;
-
-	print_window_close(pw);
-	return FALSE;
-}
-
-static void print_job_close(PrintWindow *pw, gint error)
-{
-	if (!error) print_job_finish(pw);
-
-	print_job_close_file(pw);
-	g_free(pw->job_path);
-	pw->job_path = NULL;
-
-	if (pw->job_dialog)
-		{
-		generic_dialog_close(pw->job_dialog);
-		pw->job_dialog = NULL;
-		pw->job_progress = NULL;
-		}
-
-	image_loader_free(pw->job_loader);
-	pw->job_loader = NULL;
-
-	if (pw->job_pixbuf)
-		{
-		g_object_unref(pw->job_pixbuf);
-		pw->job_pixbuf = NULL;
-		}
-
-	if (pw->dialog && !gtk_widget_get_visible(pw->dialog->dialog))
-		{
-		g_idle_add_full(G_PRIORITY_HIGH_IDLE, print_job_close_finish_cb, pw, NULL);
-		}
-}
-
-static void print_job_cancel_cb(GenericDialog *gd, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	print_job_close(pw, FALSE);
-}
-
-static void print_pref_store(PrintWindow *pw)
-{
-
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_SAVE, pw->save_settings);
-
-	if (!pw->save_settings) return;
-
-	/* only store values that are actually used in this print job, hence the if()s */
-
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_OUTPUT, pw->output);
-
-	if (pw->output == PRINT_OUTPUT_RGB_FILE)
-		{
-		pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_FORMAT, pw->output_format);
-		}
-
-	if (pw->job_format == RENDER_FORMAT_PS)
-		{
-		pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_DPI, pw->max_dpi);
-		}
-
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_UNITS, pw->paper_units);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_SIZE, pw->paper_size);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_ORIENTATION, pw->paper_orientation);
-
-	if (pw->paper_size == 0)
-		{
-		pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_CUSTOM_WIDTH, pw->paper_width);
-		pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_CUSTOM_HEIGHT, pw->paper_height);
-		}
-
-	pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_MARGIN_LEFT, pw->margin_left);
-	pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_MARGIN_RIGHT, pw->margin_right);
-	pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_MARGIN_TOP, pw->margin_top);
-	pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_MARGIN_BOTTOM, pw->margin_bottom);
-
-	if (pw->layout == PRINT_LAYOUT_PROOF)
-		{
-		pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_PROOF_WIDTH, pw->proof_width);
-		pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_PROOF_HEIGHT, pw->proof_height);
-		}
-
-	if (pw->output == PRINT_OUTPUT_PS_CUSTOM)
-		{
-		pref_list_string_set(PRINT_PREF_GROUP, PRINT_PREF_PRINTERC, pw->output_custom);
-		}
-
-	if (pw->output == PRINT_OUTPUT_RGB_FILE ||
-	    pw->output == PRINT_OUTPUT_PS_FILE)
-		{
-		tab_completion_append_to_history(pw->path_entry, pw->output_path);
-		}
-
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_TEXT, pw->text_fields);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_TEXTSIZE, pw->text_points);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_TEXTCOLOR_R, pw->text_r);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_TEXTCOLOR_G, pw->text_g);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_TEXTCOLOR_B, pw->text_b);
-
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_SOURCE, pw->source);
-	pref_list_int_set(PRINT_PREF_GROUP, PRINT_PREF_LAYOUT, pw->layout);
-
-	pref_list_double_set(PRINT_PREF_GROUP, PRINT_PREF_IMAGE_SCALE, pw->image_scale);
-}
-
-static gboolean print_job_start(PrintWindow *pw, RenderFormat format, PrintOutput output)
-{
-	GtkWidget *hbox;
-	GtkWidget *spinner;
-	gchar *msg;
-
-	if (pw->job_dialog) return FALSE;
-
-	pw->job_format = format;
-	pw->job_output = output;
-
-	if (!print_job_init(pw))
-		{
-		print_job_close(pw, TRUE);
-		return FALSE;
-		}
-
-	if (format == RENDER_FORMAT_PREVIEW)
-		{
-		print_job_render(pw);
-		return TRUE;
-		}
-
-	print_pref_store(pw);
-
-	gtk_widget_hide(pw->dialog->dialog);
-
-	pw->job_dialog = file_util_gen_dlg(_("Print"), "print_job_dialog",
-					   (GtkWidget *)gtk_window_get_transient_for(GTK_WINDOW(pw->dialog->dialog)), FALSE,
-					   print_job_cancel_cb, pw);
-
-	msg = g_strdup_printf(_("Printing %d pages to %s."), print_layout_page_count(pw), print_output_name(pw->output));
-	generic_dialog_add_message(pw->job_dialog, NULL, msg, NULL, TRUE);
-	g_free(msg);
-
-	if (pw->job_output == PRINT_OUTPUT_PS_FILE ||
-	    pw->job_output == PRINT_OUTPUT_RGB_FILE)
-		{
-		hbox = pref_box_new(pw->job_dialog->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
-		pref_label_new(hbox, _("Filename:"));
-
-		pw->job_progress_label = pref_label_new(hbox, "");
-		}
-	else
-		{
-		pw->job_progress_label = NULL;
-		}
-
-	pref_spacer(pw->job_dialog->vbox, PREF_PAD_SPACE);
-
-	hbox = pref_box_new(pw->job_dialog->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
-
-	pw->job_progress = gtk_progress_bar_new();
-	gtk_box_pack_start(GTK_BOX(hbox), pw->job_progress, TRUE, TRUE, 0);
-	gtk_widget_show(pw->job_progress);
-
-	spinner = spinner_new(NULL, SPINNER_SPEED);
-	gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0);
-	gtk_widget_show(spinner);
-
-	gtk_widget_show(pw->job_dialog->dialog);
-
-	print_job_render(pw);
-	print_job_status(pw);
-
-	return TRUE;
-}
-
-static void print_window_print_start(PrintWindow *pw)
-{
-	RenderFormat format;
-
-	switch (pw->output)
-		{
-		case PRINT_OUTPUT_RGB_FILE:
-			format = RENDER_FORMAT_RGB;
-			break;
-		case PRINT_OUTPUT_PS_FILE:
-		case PRINT_OUTPUT_PS_CUSTOM:
-		case PRINT_OUTPUT_PS_LPR:
-		default:
-			format = RENDER_FORMAT_PS;
-			break;
-		}
-
-	print_job_start(pw, format, pw->output);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * combo box util
- *-----------------------------------------------------------------------------
- */
-
-static GtkWidget *print_combo_menu(const gchar *text[], gint count, gint preferred,
-				   GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-	gint i;
-
-	combo = gtk_combo_box_text_new();
-
-	for (i = 0 ; i < count; i++)
-		{
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _(text[i]));
-		}
-
-	if (preferred >= 0 && preferred < count)
-		{
-		gtk_combo_box_set_active(GTK_COMBO_BOX(combo), preferred);
-		}
-
-	if (func) g_signal_connect(G_OBJECT(combo), "changed", func, data);
-
-	return combo;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * paper selection
- *-----------------------------------------------------------------------------
- */
-
-static GtkWidget *print_paper_menu(GtkWidget *table, gint column, gint row,
-				   PaperOrientation preferred, GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-	gint i;
-
-	pref_table_label(table, column, row, (_("Format:")), 1.0);
-
-	combo = gtk_combo_box_text_new();
-
-	i = 0;
-	while (print_paper_sizes[i].description)
-		{
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _(print_paper_sizes[i].description));
-		i++;
-		}
-
-	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), preferred);
-	if (func) g_signal_connect(G_OBJECT(combo), "changed", func, data);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_paper_select_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-	PaperSize *ps;
-	gint n;
-
-	n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-	ps = print_paper_size_nth(n);
-
-	if (!ps) return;
-
-	pw->paper_size = n;
-
-	if (pw->paper_size == 0)
-		{
-		print_window_layout_sync_paper(pw);
-		return;
-		}
-
-	if (ps->orientation == PAPER_ORIENTATION_PORTRAIT)
-		{
-		print_window_layout_set_size(pw, ps->width, ps->height);
-		}
-	else
-		{
-		print_window_layout_set_size(pw, ps->height, ps->width);
-		}
-}
-
-static void print_paper_size_cb(GtkWidget *spin, gpointer data)
-{
-	PrintWindow *pw = data;
-	gdouble value;
-
-	value = print_paper_size_convert_units(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)),
-					       pw->paper_units, PAPER_UNIT_POINTS);
-
-	if (spin == pw->paper_width_spin)
-		{
-		pw->paper_width = value;
-		}
-	else
-		{
-		pw->paper_height = value;
-		}
-
-	print_window_layout_set_size(pw, pw->paper_width, pw->paper_height);
-}
-
-static GtkWidget *print_paper_units_menu(GtkWidget *table, gint column, gint row,
-					 PaperUnits units, GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-
-	pref_table_label(table, column, row, (_("Units:")), 1.0);
-
-	combo = print_combo_menu(print_paper_units, PAPER_UNIT_COUNT, units, func, data);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_paper_units_set(PrintWindow *pw, PaperUnits units)
-{
-	PaperUnits old_units;
-
-	if (units >= PAPER_UNIT_COUNT) return;
-
-	old_units = pw->paper_units;
-	pw->paper_units = units;
-	print_window_layout_sync_paper(pw);
-
-	if ((units == PAPER_UNIT_MM || units == PAPER_UNIT_CM) !=
-	    (old_units == PAPER_UNIT_MM || old_units == PAPER_UNIT_CM))
-		{
-		print_window_layout_render(pw);
-		}
-}
-
-static void print_paper_units_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-	PaperUnits units;
-
-	units = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-
-	print_paper_units_set(pw, units);
-}
-
-static GtkWidget *print_paper_orientation_menu(GtkWidget *table, gint column, gint row,
-					       PaperOrientation preferred,
-					       GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-
-	pref_table_label(table, column, row, (_("Orientation:")), 1.0);
-
-	combo = print_combo_menu(print_paper_orientation, PAPER_ORIENTATION_COUNT, preferred, func, data);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_paper_orientation_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-	PaperOrientation o;
-
-	o = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-
-	print_window_layout_set_orientation(pw, o);
-}
-
-static void print_paper_margin_cb(GtkWidget *spin, gpointer data)
-{
-	PrintWindow *pw = data;
-	gdouble value;
-
-	value = print_paper_size_convert_units(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)),
-					       pw->paper_units, PAPER_UNIT_POINTS);
-
-	if (spin == pw->margin_left_spin)
-		{
-		pw->margin_left = CLAMP(value, 0.0, pw->paper_width);
-		}
-	else if (spin == pw->margin_right_spin)
-		{
-		pw->margin_right = CLAMP(value, 0.0, pw->paper_width);
-		}
-	else if (spin == pw->margin_top_spin)
-		{
-		pw->margin_top = CLAMP(value, 0.0, pw->paper_height);
-		}
-	else if (spin == pw->margin_bottom_spin)
-		{
-		pw->margin_bottom = CLAMP(value, 0.0, pw->paper_height);
-		}
-
-	print_window_layout_set_size(pw, pw->paper_width, pw->paper_height);
-}
-
-static GtkWidget *print_misc_menu(GtkWidget *parent_box, gint preferred,
-				  const gchar *title, const gchar *key,
-				  gint count, const gchar **text,
-				  GCallback func, gpointer data)
-{
-	GtkWidget *box;
-	GtkWidget *button = NULL;
-	gint i;
-
-	box = pref_group_new(parent_box, FALSE, title, GTK_ORIENTATION_VERTICAL);
-
-	for (i = 0; i < count; i++)
-		{
-		button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(button), _(text[i]));
-		if (i == preferred)
-			{
-			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
-			}
-		g_object_set_data(G_OBJECT(button), key, GINT_TO_POINTER(i));
-		if (func) g_signal_connect(G_OBJECT(button), "clicked", func, data);
-		gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
-		gtk_widget_show(button);
-		}
-
-	return box;
-}
-
-static void print_source_select_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) return;
-
-	pw->source = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "print_source"));
-	print_window_layout_size(pw);
-}
-
-static void print_layout_select_cb(GtkWidget *widget, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) return;
-
-	pw->layout = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "print_layout"));
-
-	print_window_layout_sync_layout(pw);
-	print_window_layout_size(pw);
-}
-
-static void print_image_scale_cb(GtkWidget *spin, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	pw->image_scale = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
-
-	print_window_layout_set_size(pw, pw->paper_width, pw->paper_height);
-}
-
-static void print_proof_size_cb(GtkWidget *spin, gpointer data)
-{
-	PrintWindow *pw = data;
-	gdouble value;
-
-	value = print_paper_size_convert_units(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)),
-					       pw->paper_units, PAPER_UNIT_POINTS);
-
-	if (spin == pw->proof_width_spin)
-		{
-		pw->proof_width = value;
-		}
-	else
-		{
-		pw->proof_height = value;
-		}
-
-	print_window_layout_render(pw);
-}
-
-static GtkWidget *print_output_menu(GtkWidget *table, gint column, gint row,
-				    PrintOutput preferred, GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-
-	pref_table_label(table, column, row, (_("Destination:")), 1.0);
-
-	combo = print_combo_menu(print_output_text, PRINT_OUTPUT_COUNT, preferred, func, data);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_custom_entry_set(PrintWindow *pw, GtkWidget *combo)
-{
-	GtkListStore *store;
-	const gchar *text;
-	GList *list;
-	GList *work;
-
-	store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
-	gtk_list_store_clear(store);
-
-	list = print_window_list_printers();
-	work = list;
-	while (work)
-		{
-		gchar *name;
-		gchar *buf;
-
-		name = work->data;
-		work = work->next;
-
-		buf = g_strdup_printf(PRINT_LPR_CUSTOM, name);
-		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
-		g_free(buf);
-		}
-	string_list_free(list);
-
-	if (pref_list_string_get(PRINT_PREF_GROUP, PRINT_PREF_PRINTERC, &text))
-		{
-		gtk_entry_set_text(GTK_ENTRY(pw->custom_entry), text);
-		}
-	else
-		{
-		text = gtk_entry_get_text(GTK_ENTRY(pw->custom_entry));
-		if (!text || strlen(text) == 0)
-			{
-			gchar *buf;
-
-			buf = g_strdup_printf(PRINT_LPR_CUSTOM, _("<printer name>"));
-			gtk_entry_set_text(GTK_ENTRY(pw->custom_entry), buf);
-			g_free(buf);
-			}
-		}
-}
-
-static void print_output_set(PrintWindow *pw, PrintOutput output)
-{
-	gboolean use_file = FALSE;
-	gboolean use_custom = FALSE;
-	gboolean use_format = FALSE;
-
-	pw->output = output;
-
-	switch (pw->output)
-		{
-		case PRINT_OUTPUT_RGB_FILE:
-			use_file = TRUE;
-			use_format = TRUE;
-			break;
-		case PRINT_OUTPUT_PS_FILE:
-			use_file = TRUE;
-			break;
-		case PRINT_OUTPUT_PS_CUSTOM:
-			use_custom = TRUE;
-			break;
-		case PRINT_OUTPUT_PS_LPR:
-		default:
-			break;
-		}
-
-	gtk_widget_set_sensitive(gtk_widget_get_parent(pw->path_entry), use_file);
-	gtk_widget_set_sensitive(gtk_widget_get_parent(pw->custom_entry), use_custom);
-	gtk_widget_set_sensitive(pw->path_format_menu, use_format);
-	gtk_widget_set_sensitive(pw->max_dpi_menu, !use_format);
-}
-
-static void print_output_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-	PrintOutput output;
-
-	output = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-
-	print_output_set(pw, output);
-}
-
-static GtkWidget *print_output_format_menu(GtkWidget * table, gint column, gint row,
-					   PrintFileFormat preferred, GCallback func, gpointer data)
-{
-	GtkWidget *combo;
-
-	combo = print_combo_menu(print_file_format_text, PRINT_FILE_COUNT, preferred, func, data);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column, column + 1, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_output_format_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-
-	pw->output_format = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-}
-
-static GtkWidget *print_output_dpi_menu(GtkWidget * table, gint column, gint row,
-					gdouble dpi, GCallback func, gpointer data)
-{
-	static gint dpilist[] = { 150, 300, 600, 1200, 0, -1};
-	GtkWidget *combo;
-	GtkListStore *store;
-	GtkCellRenderer *renderer;
-	gint current = 1;
-	gint i;
-
-	store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
-
-	i = 0;
-	while (dpilist[i] != -1)
-		{
-		GtkTreeIter iter;
-		gchar *text;
-
-		if (dpilist[i] == 0)
-			{
-			text = g_strdup(_("Unlimited"));
-			}
-		else
-			{
-			text = g_strdup_printf("%d", dpilist[i]);
-			}
-
-		gtk_list_store_append(store, &iter);
-		gtk_list_store_set(store, &iter, 0, text, 1, dpilist[i], -1);
-		g_free(text);
-
-		if (dpi == (gdouble)dpilist[i]) current = i;
-
-		i++;
-		}
-
-	combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
-	g_object_unref(store);
-
-	gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
-	if (func) g_signal_connect(G_OBJECT(combo), "changed", func, data);
-
-	renderer = gtk_cell_renderer_text_new();
-	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
-	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, "text", 0, NULL);
-
-	gtk_table_attach(GTK_TABLE(table), combo, column, column + 1, row, row + 1,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	return combo;
-}
-
-static void print_output_dpi_cb(GtkWidget *combo, gpointer data)
-{
-	PrintWindow *pw = data;
-	GtkTreeModel *store;
-	GtkTreeIter iter;
-	gint n = -1;
-
-	store = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
-	if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) return;
-	gtk_tree_model_get(store, &iter, 1, &n, -1);
-
-	pw->max_dpi = (gdouble)n;
-}
-
 static void print_text_field_set(PrintWindow *pw, TextInfo field, gboolean active)
 {
 	if (active)
@@ -3143,8 +121,6 @@
 		{
 		pw->text_fields &= ~field;
 		}
-
-	print_window_layout_render(pw);
 }
 
 static void print_text_cb_name(GtkWidget *widget, gpointer data)
@@ -3192,17 +168,39 @@
 	print_text_field_set(pw, TEXT_INFO_DIMENSIONS, active);
 }
 
-static void print_text_cb_points(GtkWidget *widget, gpointer data)
+static void print_set_font_cb(GtkWidget *widget, gpointer data)
 {
-	PrintWindow *pw = data;
+#if GTK_CHECK_VERSION(3,4,0)
+	GtkWidget *dialog;
+	char *font;
+	PangoFontDescription *font_desc;
+
+	dialog = gtk_font_chooser_dialog_new("Printer Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
+	gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->printer.font);
 
-	pw->text_points = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-	print_window_layout_render(pw);
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
+		{
+		font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
+		font = pango_font_description_to_string(font_desc);
+		g_free(options->printer.font);
+		options->printer.font = g_strdup(font);
+		g_free(font);
+		}
+
+	gtk_widget_destroy(dialog);
+#else
+	const char *font;
+
+	font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
+	options->printer.font = g_strdup(font);
+#endif
 }
 
 static void print_text_menu(GtkWidget *box, PrintWindow *pw)
 {
 	GtkWidget *group;
+	GtkWidget *hbox;
+	GtkWidget *button;
 
 	group = pref_group_new(box, FALSE, _("Show"), GTK_ORIENTATION_VERTICAL);
 
@@ -3219,290 +217,365 @@
 
 	group = pref_group_new(box, FALSE, _("Font"), GTK_ORIENTATION_VERTICAL);
 
-	pref_spin_new(group, _("Size:"), _("points"),
-		      8.0, 100.0, 1.0, 0, pw->text_points,
-		      G_CALLBACK(print_text_cb_points), pw);
+	hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
+
+#if GTK_CHECK_VERSION(3,4,0)
+	button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
+				 G_CALLBACK(print_set_font_cb), pw);
+#else
+	button = gtk_font_button_new();
+	gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Printer Font");
+	gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->printer.font);
+	g_signal_connect(G_OBJECT(button), "font-set",
+				 G_CALLBACK(print_set_font_cb),NULL);
+#endif
+	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+	gtk_widget_show(button);
 }
 
-/*
- *-----------------------------------------------------------------------------
- * print window
- *-----------------------------------------------------------------------------
- */
-
-static void print_window_close(PrintWindow *pw)
-{
-	print_window_layout_render_stop(pw);
-
-	generic_dialog_close(pw->dialog);
-	pw->dialog = NULL;
-
-	print_job_close(pw, FALSE);
-
-	file_data_unref(pw->source_fd);
-	filelist_free(pw->source_selection);
-	filelist_free(pw->source_list);
-
-	g_free(pw->output_path);
-	g_free(pw->output_custom);
-
-	g_free(pw);
-}
-
-static void print_window_print_cb(GenericDialog *gd, gpointer data)
+static gboolean paginate_cb(GtkPrintOperation *operation,
+									GtkPrintContext *context,
+									gpointer data)
 {
 	PrintWindow *pw = data;
 
-	switch (pw->output)
+	if (pw->job_render_finished)
+		{
+		return TRUE;
+		}
+	else
 		{
-		case PRINT_OUTPUT_RGB_FILE:
-		case PRINT_OUTPUT_PS_FILE:
-			g_free(pw->output_path);
-			pw->output_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(pw->path_entry)));
-			break;
-		case PRINT_OUTPUT_PS_CUSTOM:
-			g_free(pw->output_custom);
-			pw->output_custom = g_strdup(gtk_entry_get_text(GTK_ENTRY(pw->custom_entry)));
-			break;
-		case PRINT_OUTPUT_PS_LPR:
-		default:
-			break;
+		return FALSE;
 		}
+}
 
-	print_window_print_start(pw);
+/* Returns the "depth" of a layout, that is the distance from the
+ * top of the layout to the baseline of the first line in the
+ * layout. */
+int get_layout_depth(PangoLayout *layout)
+{
+  PangoLayoutLine *layout_line = pango_layout_get_line(layout,0);
+  PangoRectangle rect;
+
+  pango_layout_line_get_extents(layout_line, NULL, &rect);
+
+  return PANGO_ASCENT(rect);
 }
 
-static void print_window_cancel_cb(GenericDialog *gd, gpointer data)
+static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
+									gint page_nr, gpointer data)
 {
+	FileData *fd;
 	PrintWindow *pw = data;
+	cairo_t *cr;
+	gdouble width, height;
+	gdouble width_pixbuf_image, height_pixbuf_image;
+	gdouble width_offset;
+	gdouble height_offset;
+	GdkPixbuf *pixbuf;
+	GdkPixbuf *pixbuf_scaled;
+	PangoLayout *layout;
+	PangoFontDescription *desc;
+	GString *text = g_string_new(NULL);
+	PangoRectangle ink_rect, logical_rect;
+	gdouble depth;
+	gdouble text_padding;
+	gdouble x, y, w, h, scale;
+	gdouble pango_height;
 
-	print_window_close(pw);
+	pixbuf = g_list_nth_data(pw->print_pixbuf_queue, page_nr);
+	width_pixbuf_image = gdk_pixbuf_get_width(pixbuf);
+	height_pixbuf_image = gdk_pixbuf_get_height(pixbuf);
+
+	fd = g_list_nth_data(pw->source_selection, page_nr);
+
+	if (pw->text_fields & TEXT_INFO_FILENAME)
+		{
+		text = g_string_append(text, g_strdup(fd->name));
+		text = g_string_append(text, "\n");
+		}
+	if (pw->text_fields & TEXT_INFO_FILEDATE)
+		{
+		text = g_string_append(text, g_strdup(text_from_time(fd->date)));
+		text = g_string_append(text, "\n");
+		}
+	if (pw->text_fields & TEXT_INFO_FILESIZE)
+		{
+		text = g_string_append(text, g_strdup(text_from_size(fd->size)));
+		text = g_string_append(text, "\n");
+		}
+	if (pw->text_fields & TEXT_INFO_DIMENSIONS)
+		{
+		g_string_append_printf(text, "%d x %d", (gint)width_pixbuf_image,
+											(gint)height_pixbuf_image);
+		text = g_string_append(text, "\n");
+		}
+	if (pw->text_fields & TEXT_INFO_FILEPATH)
+		{
+		text = g_string_append(text, g_strdup(fd->path));
+		text = g_string_append(text, "\n");
+		}
+
+	cr = gtk_print_context_get_cairo_context(context);
+	width = gtk_print_context_get_width(context);
+	height = gtk_print_context_get_height(context);
+
+	if (text->len > 0)
+		{
+		text = g_string_truncate(text, text->len - 1);
+
+		layout = pango_cairo_create_layout(cr);
+
+		pango_layout_set_text(layout, text->str, -1);
+		desc = pango_font_description_from_string(options->printer.font);
+		pango_layout_set_font_description(layout, desc);
+
+		pango_layout_get_extents(layout, &ink_rect, &logical_rect);
+		x = ((gdouble)logical_rect.width / PANGO_SCALE) ;
+		y = ((gdouble)logical_rect.height / PANGO_SCALE);
+
+		pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+		pango_layout_set_text(layout, text->str, -1);
+
+		depth = (gdouble)get_layout_depth(layout);
+		text_padding = depth / 2 / PANGO_SCALE ;
+
+		pango_height = y + text_padding * 2;
+
+		}
+	else
+		{
+		pango_height = 0;
+		depth = 0;
+		text_padding = 0;
+		x = 0;
+		y = 0;
+		}
+
+	if ((width / width_pixbuf_image) < ((height - pango_height) / height_pixbuf_image))
+		{
+		w = width;
+		scale = width / width_pixbuf_image;
+		h = height_pixbuf_image * scale;
+		height_offset = (height - (h + pango_height)) / 2;
+		width_offset = 0;
+		}
+	else
+		{
+		h = height - pango_height ;
+		scale = (height - pango_height) / height_pixbuf_image;
+		w = width_pixbuf_image * scale;
+		height_offset = 0;
+		width_offset = (width - (width_pixbuf_image * scale)) / 2;
+		}
+
+	if (text->len > 0)
+		{
+		cairo_move_to(cr, (w / 2) - (x / 2) + width_offset, h + height_offset + text_padding);
+		pango_cairo_show_layout(cr, layout);
+		}
+
+	pixbuf_scaled = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
+	gdk_pixbuf_scale(pixbuf, pixbuf_scaled, 0, 0, w, h, 0, 0,  scale, scale, PRINT_MAX_INTERP);
+
+	cairo_rectangle(cr, width_offset, height_offset, w, h);
+
+	gdk_cairo_set_source_pixbuf(cr, pixbuf_scaled, width_offset, height_offset);
+	cairo_fill(cr);
+
+	if (text->len > 0)
+		{
+		g_object_unref(layout);
+		g_string_free(text, TRUE);
+		pango_font_description_free(desc);
+		}
+
+	g_object_unref(pixbuf_scaled);
+
+	return;
 }
 
-static gint print_pref_int(const gchar *key, gint fallback)
+static void begin_print(GtkPrintOperation *operation,
+						GtkPrintContext *context,
+						gpointer user_data)
 {
-	gint value;
+	PrintWindow *pw = user_data;
+	gint page_count;
+
+	page_count = print_layout_page_count(pw);
+	gtk_print_operation_set_n_pages (operation, page_count);
+
+	print_job_render_image(pw);
+}
+
 
-	if (pref_list_int_get(PRINT_PREF_GROUP, key, &value)) return value;
-	return fallback;
+GObject *option_tab_cb(GtkPrintOperation *operation, gpointer user_data)
+{
+	PrintWindow *pw = user_data;
+
+	return G_OBJECT(pw->vbox);
+}
+
+static void print_pref_store(PrintWindow *pw)
+{
+	options->printer.text_fields = pw->text_fields;
 }
 
-static gdouble print_pref_double(const gchar *key, gdouble fallback)
+static void end_print_cb(GtkPrintOperation *operation,
+								GtkPrintContext *context, gpointer data)
 {
-	gdouble value;
+	PrintWindow *pw = data;
+	GList *work;
+	GdkPixbuf *pixbuf;
+	gchar *path;
+	GtkPrintSettings *print_settings;
+	GtkPageSetup *page_setup;
+	GError *error = NULL;
+
+	print_settings = gtk_print_operation_get_print_settings(operation);
+	path = g_build_filename(get_rc_dir(), PRINT_SETTINGS, NULL);
+
+	gtk_print_settings_to_file(print_settings, path, &error);
+	if (error)
+		{
+		log_printf("Error: Print settings save failed:\n%s", error->message);
+		g_error_free(error);
+		error = NULL;
+		}
+	g_free(path);
+	g_object_unref(print_settings);
+
+	page_setup = gtk_print_operation_get_default_page_setup(operation);
+	path = g_build_filename(get_rc_dir(), PAGE_SETUP, NULL);
 
-	if (pref_list_double_get(PRINT_PREF_GROUP, key, &value)) return value;
-	return fallback;
+	gtk_page_setup_to_file(page_setup, path, &error);
+	if (error)
+		{
+		log_printf("Error: Print page setup save failed:\n%s", error->message);
+		g_error_free(error);
+		error = NULL;
+		}
+	g_free(path);
+	g_object_unref(page_setup);
+
+	print_pref_store(pw);
+
+	work = pw->print_pixbuf_queue;
+	while (work)
+		{
+		pixbuf = work->data;
+		if (pixbuf)
+			{
+			g_object_unref(pixbuf);
+			}
+		work = work->next;
+		}
+	g_list_free(pw->print_pixbuf_queue);
+	g_free(pw);
 }
 
 void print_window_new(FileData *fd, GList *selection, GList *list, GtkWidget *parent)
 {
 	PrintWindow *pw;
-	GdkGeometry geometry;
-	GtkWidget *main_box;
 	GtkWidget *vbox;
-	GtkWidget *label;
-	GtkWidget *combo;
-	GtkWidget *box;
-	GtkWidget *table;
+	GtkPrintOperation *operation;
+	GtkPageSetup *page_setup;
+	gchar *uri;
+	const gchar *dir;
+	GError *error = NULL;
+	gchar *path;
+	GtkPrintSettings *settings;
 
 	pw = g_new0(PrintWindow, 1);
 
-	pw->source_fd = file_data_ref(fd);
 	pw->source_selection = file_data_process_groups_in_selection(selection, FALSE, NULL);
-	pw->source_list = list;
-
-	pw->source = print_pref_int(PRINT_PREF_SOURCE, PRINT_SOURCE_SELECTION);
-	pw->layout = print_pref_int(PRINT_PREF_LAYOUT, PRINT_LAYOUT_IMAGE);
-
-	pw->image_scale = print_pref_double(PRINT_PREF_IMAGE_SCALE, 100.0);
-
-	pw->output = print_pref_int(PRINT_PREF_OUTPUT, PRINT_OUTPUT_PS_LPR);
-	pw->output_format = print_pref_int(PRINT_PREF_FORMAT, PRINT_FILE_JPG_NORMAL);
-
-	pw->max_dpi = print_pref_double(PRINT_PREF_DPI, PRINT_PS_DPI_DEFAULT);
-
-	pw->paper_units = print_pref_int(PRINT_PREF_UNITS, paper_unit_default());
-	pw->paper_size = print_pref_int(PRINT_PREF_SIZE, 1);
-	if (pw->paper_size == 0 ||
-	    !print_paper_size_lookup(pw->paper_size, &pw->paper_width, &pw->paper_height))
-		{
-		pw->paper_width = print_pref_double(PRINT_PREF_CUSTOM_WIDTH, 360.0);
-		pw->paper_height = print_pref_double(PRINT_PREF_CUSTOM_HEIGHT, 720.0);
-		}
-	pw->paper_orientation = print_pref_int(PRINT_PREF_ORIENTATION, PAPER_ORIENTATION_PORTRAIT);
-
-	pw->margin_left = print_pref_double(PRINT_PREF_MARGIN_LEFT, PRINT_MARGIN_DEFAULT);
-	pw->margin_right = print_pref_double(PRINT_PREF_MARGIN_RIGHT, PRINT_MARGIN_DEFAULT);
-	pw->margin_top = print_pref_double(PRINT_PREF_MARGIN_TOP, PRINT_MARGIN_DEFAULT);
-	pw->margin_bottom = print_pref_double(PRINT_PREF_MARGIN_BOTTOM, PRINT_MARGIN_DEFAULT);
-
-	pw->proof_width = print_pref_double(PRINT_PREF_PROOF_WIDTH, PRINT_PROOF_DEFAULT_SIZE);
-	pw->proof_height = print_pref_double(PRINT_PREF_PROOF_HEIGHT, PRINT_PROOF_DEFAULT_SIZE);
-
-	pw->text_fields = print_pref_int(PRINT_PREF_TEXT, TEXT_INFO_FILENAME);
-	pw->text_points = print_pref_int(PRINT_PREF_TEXTSIZE, 10);
-	pw->text_r = print_pref_int(PRINT_PREF_TEXTCOLOR_R, 0);
-	pw->text_g = print_pref_int(PRINT_PREF_TEXTCOLOR_G, 0);
-	pw->text_b = print_pref_int(PRINT_PREF_TEXTCOLOR_B, 0);
-
-	pw->save_settings = print_pref_int(PRINT_PREF_SAVE, TRUE);
-
-	pw->dialog = file_util_gen_dlg(_("Print"), "print_dialog",
-				       parent, FALSE,
-				       print_window_cancel_cb, pw);
-
-	geometry.min_width = DEFAULT_MINIMAL_WINDOW_SIZE;
-	geometry.min_height = DEFAULT_MINIMAL_WINDOW_SIZE;
-	geometry.base_width = PRINT_DLG_WIDTH;
-	geometry.base_height = PRINT_DLG_HEIGHT;
-	gtk_window_set_geometry_hints(GTK_WINDOW(pw->dialog->dialog), NULL, &geometry,
-				      GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
-
-	pw->print_button = generic_dialog_add_button(pw->dialog, GTK_STOCK_PRINT, NULL, print_window_print_cb, TRUE);
-
-	main_box = pref_box_new(pw->dialog->vbox, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP);
-
-	pw->notebook = gtk_notebook_new();
-	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(pw->notebook), GTK_POS_TOP);
-	gtk_box_pack_start(GTK_BOX(main_box), pw->notebook, FALSE, FALSE, 0);
-
-	/* layout tab */
+	pw->text_fields = options->printer.text_fields;
 
 	vbox = gtk_vbox_new(FALSE, 0);
 	gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
 	gtk_widget_show(vbox);
-	label = gtk_label_new(_("Layout"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(pw->notebook), vbox, label);
-
-	print_misc_menu(vbox, pw->source, _("Source"), "print_source",
-			PRINT_SOURCE_COUNT, print_source_text,
-			G_CALLBACK(print_source_select_cb), pw);
-
-	box = print_misc_menu(vbox, pw->layout, _("Layout"), "print_layout",
-			      PRINT_LAYOUT_COUNT, print_layout_text,
-			      G_CALLBACK(print_layout_select_cb), pw);
-
-	pref_spacer(box, PREF_PAD_GROUP);
-
-	table = pref_table_new(box, 2, 2, FALSE, FALSE);
-
-	pw->image_scale_spin = pref_table_spin(table, 0, 0, _("Image size:"), "%",
-					       5.0, 100.0, 1.0, 0, pw->image_scale,
-					       G_CALLBACK(print_image_scale_cb), pw);
-
-	label = pref_table_label(table, 0, 1, _("Proof size:"), 1.0);
-	pw->proof_group = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
-	pref_link_sensitivity(label, pw->proof_group);
-
-	pw->proof_width_spin = pref_spin_new(pw->proof_group, NULL, NULL,
-					     0.0, 50.0, 0.1, 3, 0.0,
-					     G_CALLBACK(print_proof_size_cb), pw);
-	pw->proof_height_spin = pref_spin_new(pw->proof_group, "x", NULL,
-					      0.0, 50.0, 0.1, 3, 0.0,
-					      G_CALLBACK(print_proof_size_cb), pw);
-
-	/* text tab */
-
-	vbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
-	gtk_widget_show(vbox);
-	label = gtk_label_new(_("Text"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(pw->notebook), vbox, label);
 
 	print_text_menu(vbox, pw);
-
-	/* paper tab */
-
-	vbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
-	gtk_widget_show(vbox);
-	label = gtk_label_new(_("Paper"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(pw->notebook), vbox, label);
-
-	table = pref_table_new(vbox, 2, 4, FALSE, FALSE);
+	pw->vbox = vbox;
 
-	print_paper_menu(table, 0, 0, pw->paper_size, G_CALLBACK(print_paper_select_cb), pw);
+	pw->print_pixbuf_queue = NULL;
+	pw->job_render_finished = FALSE;
+	pw->job_page = 0;
 
-	label = pref_table_label(table, 0, 1, (_("Size:")), 1.0);
-	box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
-	pw->paper_width_spin = pref_spin_new(box, NULL, NULL,
-					     1.0, 10000.0, 1.0, 2, 66,
-					     G_CALLBACK(print_paper_size_cb), pw);
-	pw->paper_height_spin = pref_spin_new(box, "x", NULL,
-					      1.0, 10000.0, 1.0, 2, 66,
-					      G_CALLBACK(print_paper_size_cb), pw);
-	pref_link_sensitivity(label, pw->paper_width_spin);
+	operation = gtk_print_operation_new();
+	settings = gtk_print_settings_new();
 
-	pw->paper_units_menu = print_paper_units_menu(table, 0, 2, pw->paper_units,
-					G_CALLBACK(print_paper_units_cb), pw);
-
-	print_paper_orientation_menu(table, 0, 3, pw->paper_orientation,
-				     G_CALLBACK(print_paper_orientation_cb), pw);
+	gtk_print_operation_set_custom_tab_label(operation, "Options");
+	gtk_print_operation_set_use_full_page(operation, TRUE);
+	gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
+	gtk_print_operation_set_embed_page_setup(operation, TRUE);
+	gtk_print_operation_set_allow_async (operation, TRUE);
+	dir = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
+	if (dir == NULL)
+		{
+		dir = g_get_home_dir();
+		}
 
-	box = pref_group_new(vbox, FALSE, _("Margins"), GTK_ORIENTATION_VERTICAL);
-	table = pref_table_new(box, 4, 2, FALSE, FALSE);
-	pw->margin_left_spin = pref_table_spin(table, 0, 0, _("Left:"), NULL,
-					0.0, 50.0, 0.1, 3, 0.0,
-					G_CALLBACK(print_paper_margin_cb), pw);
-	pw->margin_right_spin = pref_table_spin(table, 2, 0, _("Right:"), NULL,
-					0.0, 50.0, 0.1, 3, 0.0,
-					G_CALLBACK(print_paper_margin_cb), pw);
-	pw->margin_top_spin = pref_table_spin(table, 0, 1, _("Top:"), NULL,
-					0.0, 50.0, 0.1, 3, 0.0,
-					G_CALLBACK(print_paper_margin_cb), pw);
-	pw->margin_bottom_spin = pref_table_spin(table, 2, 1, _("Bottom:"), NULL,
-					0.0, 50.0, 0.1, 3, 0.0,
-					G_CALLBACK(print_paper_margin_cb), pw);
+	uri = g_build_filename("file:/", dir, "geeqie-file.pdf", NULL);
+	gtk_print_settings_set(settings, GTK_PRINT_SETTINGS_OUTPUT_URI, uri);
+	g_free(uri);
 
-	/* printer tab */
+	path = g_build_filename(get_rc_dir(), PRINT_SETTINGS, NULL);
+	gtk_print_settings_load_file(settings, path, &error);
+	if (error)
+		{
+		log_printf("Error: Printer settings load failed:\n%s", error->message);
+		g_error_free(error);
+		error = NULL;
+		}
+	gtk_print_operation_set_print_settings(operation, settings);
+	g_free(path);
 
-	vbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
-	gtk_widget_show(vbox);
-	label = gtk_label_new(_("Printer"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(pw->notebook), vbox, label);
-
-	table = pref_table_new(vbox, 2, 5, FALSE, FALSE);
-	print_output_menu(table, 0, 0, pw->output, G_CALLBACK(print_output_cb), pw);
+	page_setup = gtk_page_setup_new();
+	path = g_build_filename(get_rc_dir(), PAGE_SETUP, NULL);
+	gtk_page_setup_load_file(page_setup, path, &error);
+	if (error)
+		{
+		log_printf("Error: Print page setup load failed:\n%s", error->message);
+		g_error_free(error);
+		error = NULL;
+		}
+	gtk_print_operation_set_default_page_setup(operation, page_setup);
+	g_free(path);
 
-	label = pref_table_label(table, 0, 1, _("Custom printer:"), 1.0);
-	combo = history_combo_new(&pw->custom_entry, NULL, "print_custom", -1);
-	print_custom_entry_set(pw, combo);
-	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
-
-	pref_link_sensitivity(label, combo);
+	g_signal_connect (G_OBJECT (operation), "begin-print",
+					G_CALLBACK (begin_print), pw);
+	g_signal_connect (G_OBJECT (operation), "draw-page",
+					G_CALLBACK (draw_page), pw);
+	g_signal_connect (G_OBJECT (operation), "end-print",
+					G_CALLBACK (end_print_cb), pw);
+	g_signal_connect (G_OBJECT (operation), "create-custom-widget",
+					G_CALLBACK (option_tab_cb), pw);
+	g_signal_connect (G_OBJECT (operation), "paginate",
+					G_CALLBACK (paginate_cb), pw);
 
-	label = pref_table_label(table, 0, 2, _("File:"), 1.0);
-	combo = tab_completion_new_with_history(&pw->path_entry, NULL, "print_path", -1, NULL, pw);
-	tab_completion_add_select_button(pw->path_entry, NULL, FALSE);
-	gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3,
-			 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-	gtk_widget_show(combo);
+	gtk_print_operation_set_n_pages(operation, print_layout_page_count(pw));
 
-	pref_link_sensitivity(label, combo);
+	gtk_print_operation_run(operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+												GTK_WINDOW (parent), &error);
 
-	label = pref_table_label(table, 0, 3, _("File format:"), 1.0);
-	pw->path_format_menu = print_output_format_menu(table, 1, 3, pw->output_format,
-							G_CALLBACK(print_output_format_cb), pw);
-	pref_link_sensitivity(label, pw->path_format_menu);
+	if (error)
+		{
+		GtkWidget *dialog;
 
-	label = pref_table_label(table, 0, 4, _("DPI:"), 1.0);
-	pw->max_dpi_menu = print_output_dpi_menu(table, 1, 4, pw->max_dpi,
-						 G_CALLBACK(print_output_dpi_cb), pw);
-	pref_link_sensitivity(label, pw->max_dpi_menu);
-
-	print_output_set(pw, pw->output);
+		dialog = gtk_message_dialog_new(GTK_WINDOW (parent),
+								GTK_DIALOG_DESTROY_WITH_PARENT,
+								GTK_MESSAGE_ERROR,
+								GTK_BUTTONS_CLOSE,
+								"%s", error->message);
+		g_error_free (error);
 
-	vbox = print_window_layout_setup(pw, main_box);
-	pref_checkbox_new_int(vbox, _("Remember print settings"), pw->save_settings, &pw->save_settings);
+		g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
 
-	print_window_layout_sync_layout(pw);
-	print_window_layout_sync_paper(pw);
+		gtk_widget_show (dialog);
+		}
 
-	gtk_widget_show(pw->notebook);
-	gtk_widget_show(pw->dialog->dialog);
+	g_object_unref(page_setup);
+	g_object_unref(settings);
 }
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/rcfile.c	Fri Sep 07 19:09:43 2018 +0100
+++ b/src/rcfile.c	Thu Sep 20 19:29:39 2018 +0100
@@ -494,6 +494,10 @@
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.auto_padding);
 	WRITE_NL(); WRITE_CHAR(*options, cp_mv_rn.auto_end);
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.formatted_start);
+
+	/* printer */
+	WRITE_NL(); WRITE_CHAR(*options, printer.font);
+	WRITE_NL(); WRITE_INT(*options, printer.text_fields);
 }
 
 static void write_color_profile(GString *outstr, gint indent)
@@ -829,6 +833,10 @@
 		if (READ_CHAR(*options, cp_mv_rn.auto_end)) continue;
 		if (READ_INT(*options, cp_mv_rn.formatted_start)) continue;
 
+		/* printer */
+		if (READ_CHAR(*options, printer.font)) continue;
+		if (READ_INT(*options, printer.text_fields)) continue;
+
 		/* Dummy options */
 		if (READ_DUMMY(*options, image.dither_quality, "deprecated since 2012-08-13")) continue;