Include a Other Software section in Help file
[geeqie.git] / src / print.c
index fde8576..dbdf031 100644 (file)
 /*
- * Geeqie
- * (C) 2004 John Ellis
+ * Copyright (C) 2018 The Geeqie Team
  *
- * Author: John Ellis
+ * Author: Colin Clark
  *
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
 #include "main.h"
 #include "print.h"
 
-#include "filelist.h"
-#include "image.h"
+#include "exif.h"
+#include "filedata.h"
 #include "image-load.h"
+#include "osd.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>
-
-
-#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
+#define PRINT_SETTINGS "print_settings" // filename save printer settings
+#define PAGE_SETUP "page_setup" // filename save page setup
 
 /* 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"
-
-
-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;
-
-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_BILINEAR
 
+/* reverse order is important */
 typedef enum {
-       TEXT_INFO_FILENAME = 1 << 0,
-       TEXT_INFO_FILEDATE = 1 << 1,
-       TEXT_INFO_FILESIZE = 1 << 2,
-       TEXT_INFO_DIMENSIONS = 1 << 3,
-       TEXT_INFO_FILEPATH = 1 << 4
-} TextInfo;
+       FOOTER_2,
+       FOOTER_1,
+       HEADER_2,
+       HEADER_1
+} TextPosition;
 
 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;
-
-       gint layout_idle_id;
-
-       gint 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;
-
-       gint paper_units;
-       gint paper_size;
-       gdouble paper_width;
-       gdouble paper_height;
-       gint 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;
+       gint job_page;
+       GtkTextBuffer *page_text;
+       gchar *template_string;
+       GtkWidget *parent;
        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 gint 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 < 0 || output >= PRINT_OUTPUT_COUNT) return "";
-
-       return _(print_output_text[output]);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * data
- *-----------------------------------------------------------------------------
- */
-
-
-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 _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
+       GList *print_pixbuf_queue;
+       gboolean job_render_finished;
+       GSList *image_group;
+       GSList *page_group;
 };
 
-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 }
-};
-
-
-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 char *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 (int)(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)
+static gint print_layout_page_count(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);
+       gint images;
 
-       gtk_widget_set_sensitive(pw->page_label, (total > 0));
+       images = g_list_length(pw->source_selection);
 
-       gtk_widget_set_sensitive(pw->button_back, (pw->proof_page > 0));
-       gtk_widget_set_sensitive(pw->button_next, (pw->proof_page < total - 1));
+       if (images < 1 ) return 0;
 
-       gtk_widget_set_sensitive(pw->print_button, total > 0);
+       return images;
 }
 
-static void print_window_layout_render_stop(PrintWindow *pw)
-{
-       if (pw->layout_idle_id != -1)
-               {
-               g_source_remove(pw->layout_idle_id);
-               pw->layout_idle_id = -1;
-               }
-}
+static gboolean print_job_render_image(PrintWindow *pw);
 
-static gboolean print_window_layout_render_idle(gpointer data)
+static void print_job_render_image_loader_done(ImageLoader *il, gpointer data)
 {
        PrintWindow *pw = data;
+       GdkPixbuf *pixbuf;
 
-       print_job_close(pw, FALSE);
-       print_job_start(pw, RENDER_FORMAT_PREVIEW, 0);
-
-       pw->layout_idle_id = -1;
-       return FALSE;
-}
+       pixbuf = image_loader_get_pixbuf(il);
 
-static void print_window_layout_render(PrintWindow *pw)
-{
-       gdouble proof_w, proof_h;
+       g_object_ref(pixbuf);
+       pw->print_pixbuf_queue = g_list_append(pw->print_pixbuf_queue, pixbuf);
 
-       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;
+       image_loader_free(pw->job_loader);
+       pw->job_loader = NULL;
 
-       print_window_layout_status(pw);
+       pw->job_page++;
 
-       if (pw->layout_idle_id == -1)
+       if (!print_job_render_image(pw))
                {
-               pw->layout_idle_id = g_idle_add(print_window_layout_render_idle, pw);
+               pw->job_render_finished = TRUE;
                }
 }
 
-static void print_window_layout_size(PrintWindow *pw)
+static gboolean print_job_render_image(PrintWindow *pw)
 {
-       GdkPixbuf *pixbuf;
-       gdouble width;
-       gdouble height;
-       gint sw, sh;
+       FileData *fd = NULL;
 
-       if (!pw->layout_image) return;
+       fd = g_list_nth_data(pw->source_selection, pw->job_page);
+       if (!fd) return FALSE;
 
-       if (pw->paper_orientation == PAPER_ORIENTATION_LANDSCAPE)
-               {
-               width = pw->paper_height;
-               height = pw->paper_width;
-               }
-       else
-               {
-               width = pw->paper_width;
-               height = pw->paper_height;
-               }
+       image_loader_free(pw->job_loader);
+       pw->job_loader = NULL;
 
-       pw->layout_width = width;
-       pw->layout_height = height;
+       pw->job_loader = image_loader_new(fd);
+       g_signal_connect(G_OBJECT(pw->job_loader), "done",
+                                               (GCallback)print_job_render_image_loader_done, pw);
 
-       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)
+       if (!image_loader_start(pw->job_loader))
                {
-               pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, sw, sh);
-               image_change_pixbuf(pw->layout_image, pixbuf, 0.0);
-               g_object_unref(pixbuf);
+               image_loader_free(pw->job_loader);
+               pw->job_loader= NULL;
                }
 
-       print_window_layout_render(pw);
-       print_window_layout_status(pw);
+       return TRUE;
 }
 
-static gint print_layout_page_count(PrintWindow *pw)
+static void print_set_font_cb(GtkWidget *widget, gpointer data)
 {
-       gint images;
-       gint images_per_page;
-       gint pages;
+       gpointer option;
 
-       if (pw->layout_width - pw->margin_left - pw->margin_right <= 0.0 ||
-           pw->layout_height - pw->margin_top - pw->margin_bottom <= 0.0)
+       if (g_strcmp0(data, "Image text font") == 0)
                {
-               return 0;
+               option = options->printer.image_font;
                }
-
-       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)
+       else
                {
-               case PRINT_LAYOUT_PROOF:
-                       images_per_page = pw->proof_columns * pw->proof_rows;
-                       break;
-               case PRINT_LAYOUT_IMAGE:
-               default:
-                       images_per_page = 1;
-                       break;
+               option = options->printer.page_font;
                }
 
-       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 = -1;
-
-       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));
-               if (debug) printf("adding printer: %s\n", 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(int fd)
-{
-       pipe_handler_error = TRUE;
-}
-
-static PipeError *pipe_handler_new(void)
-{
-       struct sigaction new_action;
-       PipeError *pe;
-
-       if (pipe_handler_data)
-               {
-               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;
-
-       /* 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) 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 gint 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 gint print_job_ps_init(PrintWindow *pw)
-{
-       FILE *f;
-       PipeError *pe;
-       const gchar *cmd = NULL;
-       const gchar *path = NULL;
-       gchar *lc_pointer;
-       gint 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. */
-       fprintf(f, "%%!PS-Adobe-3.0\n");
-       fprintf(f, "%%%%Creator: %s Version %s\n", GQ_APPNAME, VERSION);
-       fprintf(f, "%%%%CreationDate: \n");
-       fprintf(f, "%%%%LanguageLevel 2\n");
-       fprintf(f, "%%%%DocumentMedia: \n");
-       fprintf(f, "%%%%Orientation: %s\n",
-               (pw->paper_orientation == PAPER_ORIENTATION_PORTRAIT) ? "Portrait" : "Landscape");
-       fprintf(f, "%%%%BoundingBox: %f %f %f %f\n",
-               0.0, 0.0, pw->paper_width, pw->paper_height);
-       fprintf(f, "%%%%Pages: %d\n", print_layout_page_count(pw));
-       fprintf(f, "%%%%PageOrder: Ascend\n");
-       fprintf(f, "%%%%Title:\n");
-
-       /* setup page size, coordinates (do we really need this?) */
-#if 0
-       fprintf(f, "<<\n");
-       fprintf(f, "/PageSize [%f %f]\n", pw->layout_width, pw->layout_height);
-       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);
-       fprintf(f, "/Orientation %d\n",
-               (pw->paper_orientation == PAPER_ORIENTATION_PORTRAIT) ? 0 : 1);
-       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 gint print_job_ps_page_new(PrintWindow *pw, gint page)
-{
-       FILE *f;
-       PipeError *pe;
-       gchar *lc_pointer;
-       gint 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();
-
-       fprintf(f, "%%%% page %d\n", page + 1);
-
-       if (pw->paper_orientation == PAPER_ORIENTATION_LANDSCAPE)
-               {
-               fprintf(f, "/pagelevel save def\n");
-               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 gint print_job_ps_page_done(PrintWindow *pw)
-{
-       FILE *f;
-       PipeError *pe;
-       gchar *lc_pointer;
-       gint 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)
-               {
-               fprintf(f, "pagelevel restore\n");
-               }
-
-       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';
-
-       fprintf(f, text);
-}                                                                                                                         
-static gint 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];
-       gint 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();
-
-       fprintf(f, "gsave\n");
-       fprintf(f, "[%f 0 0 %f %f %f] concat\n", w, h, x, pw->layout_height - h - y);
-       fprintf(f, "/buf %d string def\n", sw * 3);
-       fprintf(f, "%d %d %d\n", sw, sh, 8);
-       fprintf(f, "[%d 0 0 -%d 0 %d]\n", sw, sh, sh);
-       fprintf(f, "{ currentfile buf readhexstring pop }\n");
-       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)
-                               {
-                               fprintf(f, "\n");
-                               c = 0;
-                               }
-                       }
-               }
-       if (c > 0) fprintf(f, "\n");
-       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;
-}
-
-static const gchar *ps_text_to_hex_array(FILE *f, const gchar *text, gdouble x, gdouble y)
-{
-       static gchar hex_digits[] = "0123456789abcdef";
-       const gchar *p;
-
-       if (!text) return NULL;
-
-       fprintf(f, "%f %f moveto\n", x, y);
-       fprintf(f, "<");
-
-       /* fixme: convert utf8 to ascii or proper locale string.. */
-
-       p = text;
-       while (*p != '\0' && *p != '\n')
-               {
-               gchar text[3];
-
-               text[0] = hex_digits[*p >> 4];
-               text[1] = hex_digits[*p & 0xf];
-               text[2] = '\0';
-
-               fprintf(f, text);
-
-               p++;
-               }
-
-       fprintf(f, ">\n");
-       fprintf(f, "dup stringwidth pop 2 div neg 0 rmoveto show\n");
-
-       return p;
-}
-
-static void ps_text_parse(FILE *f, const gchar *text, gdouble x, gdouble y, gdouble point_size)
-{
-       const gchar *p;
-
-       if (!text) return;
-
-       fprintf(f, "newpath\n");
-
-       p = text;
-       while (p && *p != '\0')
-               {
-               p = ps_text_to_hex_array(f, p, x, y);
-               if (p && *p == '\n') p++;
-               y -= point_size;
-               }
-
-       fprintf(f, "closepath\n");
-}
-
-static gint 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)
-{
-       FILE *f;
-       PipeError *pe;
-       gchar *lc_pointer;
-       gint ret;
-
-       if (!text) return TRUE;
-
-       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();
-
-       fprintf(f, "/Sans findfont\n");
-       fprintf(f, "%f scalefont\n", point_size);
-       fprintf(f, "setfont\n");
-
-       fprintf(f, "%f %f %f setrgbcolor\n", (gdouble)r / 255.0, (gdouble)g / 255.0, (gdouble)b / 255.0);
-       ps_text_parse(f, text, x, pw->layout_height - y - point_size, point_size);
-
-       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 gint print_job_ps_end(PrintWindow *pw)
-{
-       FILE *f;
-       PipeError *pe;
-       gchar *lc_pointer;
-       gint 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();
-
-       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 gint 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 = 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 gint print_job_rgb_page_done(PrintWindow *pw)
-{
-       gchar *pathl;
-       gint 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 gint 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"))
-                       {
-                       int int_dpi;
-                       g_object_get(settings, "gtk-xft-dpi", &int_dpi, NULL);
-                       dpi = (gdouble)int_dpi / PANGO_SCALE;
-                       }
-
-               if (dpi < 25.0)
-                       {
-                       static gint warned = FALSE;
-                       gdouble fallback_dpi = 96.0;
-
-                       if (!warned)
-                               {
-                               if (dpi == 0.0)
-                                       {
-                                       printf("pango dpi unknown, assuming %.0f\n", fallback_dpi);
-                                       }
-                               else
-                                       {
-                                       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 gint 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 gint 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 gint 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 gint print_job_preview_page_done(PrintWindow *pw)
-{
-       return TRUE;
-}
-
-static gint 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 gint 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 gint 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 gint 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 gint 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 gint print_job_page_image(PrintWindow *pw, GdkPixbuf *pixbuf,
-                                gdouble x, gdouble y, gdouble w, gdouble h,
-                                gdouble offx, gdouble offy)
-{
-       gint 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 gint print_job_page_text(PrintWindow *pw, const gchar *text, gdouble point_size,
-                               gdouble x, gdouble y, gdouble width,
-                               guint8 r, guint8 g, guint8 b)
-{
-       gint 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 gint print_job_render_image(PrintWindow *pw);
-static gint 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_VISIBLE(pw->dialog->dialog)) parent = pw->dialog->dialog;
-
-       gd = generic_dialog_new(_("Printing error"), GQ_WMCLASS, "print_warning",
-                               parent, TRUE, NULL, NULL);
-       generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, NULL, TRUE);
-
-       buf = g_strdup_printf(_("An error occured printing to %s."), print_output_name(pw->output));
-       generic_dialog_add_message(gd, GTK_STOCK_DIALOG_ERROR, _("Printing error"), buf);
-       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 gint print_job_text_image(PrintWindow *pw, const gchar *path,
-                                gdouble x, gdouble y, gdouble width,
-                                gint sw, gint sh, gint proof)
-{
-       GString *string;
-       gint space = FALSE;
-       gint newline = FALSE;
-       gint ret;
-
-       if (pw->text_fields == 0) return TRUE;
-
-       string = g_string_new("");
-       path = pw->job_loader->fd->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(pw->job_loader->fd->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(pw->job_loader->fd->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;
-       gint success = TRUE;
-
-       pixbuf = image_loader_get_pixbuf(il);
-       if (pixbuf)
-               {
-               gdouble sw, sh;
-               gdouble dw, dh;
-               gdouble x, y, w, h;
-               gdouble scale;
-               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;
-                       scale = w / sw;
-                       }
-               else
-                       {
-                       h = dh;
-                       w = dh / sh *sw;
-                       scale = h / sh;
-                       }
-
-               if (pw->image_scale >= 5)
-                       {
-                       w = w * (gdouble)pw->image_scale / 100.0;
-                       h = h * (gdouble)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, pw->job_loader->fd->path, x, y, dw, sw, sh, FALSE));
-               }
-
-       image_loader_free(pw->job_loader);
-       pw->job_loader = NULL;
-
-       if (pw->job_format == RENDER_FORMAT_PREVIEW)
-               {
-               print_job_done(pw);
-               return;
-               }
-
-       success = (success && print_job_page_done(pw));
-       if (!success)
-               {
-               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);
-               }
-}
-
-static gint print_job_render_image(PrintWindow *pw)
-{
-       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;
-               }
-
-       image_loader_free(pw->job_loader);
-       pw->job_loader = NULL;
-
-       if (!fd) return FALSE;
-
-       pw->job_loader = image_loader_new(fd);
-       if (!image_loader_start(pw->job_loader, print_job_render_image_loader_done, pw))
-               {
-               image_loader_free(pw->job_loader);
-               pw->job_loader= NULL;
-               }
-
-       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;
-       gdouble scale;
-       gint 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);
-
-       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;
-               scale = icon_w / w;
-               }
-       else
-               {
-               icon_h = pw->proof_height;
-               icon_w = pw->proof_height / h * w;
-               scale = icon_h / h;
-               }
-
-       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, pw->job_loader->fd->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 gint 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);
-       if (!image_loader_start(pw->job_loader, print_job_render_proof_loader_done, pw))
-               {
-               image_loader_free(pw->job_loader);
-               pw->job_loader = NULL;
-               }
-
-       return TRUE;
-}
-
-static void print_job_render(PrintWindow *pw)
-{
-       gdouble proof_w, proof_h;
-       gint 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 gint print_job_init(PrintWindow *pw)
-{
-       gint 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 gint print_job_finish(PrintWindow *pw)
-{
-       gint 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_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);
-               }
-}
-
-static gint 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);
-
-       {
-       gchar *title = g_strdup_printf("%s - %s", _("Print"), GQ_APPNAME);
-       pw->job_dialog = file_util_gen_dlg(title, GQ_WMCLASS, "print_job_dialog",
-                                          (GtkWidget *)gtk_window_get_transient_for(GTK_WINDOW(pw->dialog->dialog)), FALSE,
-                                          print_job_cancel_cb, pw);
-       g_free(title);
-       }
-
-       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);
-       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_new_text();
-
-       for (i = 0 ; i < count; i++)
-               {
-               gtk_combo_box_append_text(GTK_COMBO_BOX(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,
-                                  gint preferred, GCallback func, gpointer data)
-{
-       GtkWidget *combo;
-       gint i;
-
-       pref_table_label(table, column, row, (_("Format:")), 1.0);
+#if GTK_CHECK_VERSION(3,4,0)
+       GtkWidget *dialog;
+       char *font;
+       PangoFontDescription *font_desc;
 
-       combo = gtk_combo_box_new_text();
+       dialog = gtk_font_chooser_dialog_new(data, GTK_WINDOW(gtk_widget_get_toplevel(widget)));
+       gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), option);
 
-       i = 0;
-       while (print_paper_sizes[i].description)
+       if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
                {
-               gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(print_paper_sizes[i].description));
-               i++;
+               font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
+               font = pango_font_description_to_string(font_desc);
+               g_free(option);
+               option = g_strdup(font);
+               g_free(font);
                }
 
-       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);
+       gtk_widget_destroy(dialog);
+#else
+       const char *font;
 
-       return combo;
+       font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
+       option = g_strdup(font);
+#endif
 }
 
-static void print_paper_select_cb(GtkWidget *combo, gpointer data)
+static gint set_toggle(GSList *list, TextPosition pos)
 {
-       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;
-               }
+       GtkToggleButton *current_sel;
+       GtkToggleButton *new_sel;
+       gint new_pos = - 1;
 
-       if (ps->orientation == PAPER_ORIENTATION_PORTRAIT)
-               {
-               print_window_layout_set_size(pw, ps->width, ps->height);
-               }
-       else
+       current_sel = g_slist_nth(list, pos)->data;
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(current_sel)))
                {
-               print_window_layout_set_size(pw, ps->height, ps->width);
+               new_pos = (pos - 1);
+               if (new_pos < 0)
+                       {
+                       new_pos = HEADER_1;
+                       }
+               new_sel = g_slist_nth(list, new_pos)->data;
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(new_sel), TRUE);
                }
+       return new_pos;
 }
 
-static void print_paper_size_cb(GtkWidget *spin, gpointer data)
+static void image_text_position_h1_cb(GtkWidget *widget, gpointer data)
 {
        PrintWindow *pw = data;
-       gdouble value;
+       gint new_set;
 
-       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
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
                {
-               pw->paper_height = value;
+               new_set = set_toggle(pw->page_group, HEADER_1);
+               if (new_set >= 0)
+                       {
+                       options->printer.page_text_position = new_set;
+                       }
+               options->printer.image_text_position = HEADER_1;
                }
-
-       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)
+static void image_text_position_h2_cb(GtkWidget *widget, 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);
+       PrintWindow *pw = data;
+       gint new_set;
 
-       return combo;
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               new_set = set_toggle(pw->page_group, HEADER_2);
+               if (new_set >= 0)
+                       {
+                       options->printer.page_text_position = new_set;
+                       }
+               options->printer.image_text_position = HEADER_2;
+               }
 }
 
-static void print_paper_units_set(PrintWindow *pw, PaperUnits units)
+static void image_text_position_f1_cb(GtkWidget *widget, gpointer data)
 {
-       PaperUnits old_units;
-
-       if (units < 0 || units >= PAPER_UNIT_COUNT) return;
-
-       old_units = pw->paper_units;
-       pw->paper_units = units;
-       print_window_layout_sync_paper(pw);
+       PrintWindow *pw = data;
+       gint new_set;
 
-       if ((units == PAPER_UNIT_MM || units == PAPER_UNIT_CM) !=
-           (old_units == PAPER_UNIT_MM || old_units == PAPER_UNIT_CM))
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
                {
-               print_window_layout_render(pw);
+               new_set = set_toggle(pw->page_group, FOOTER_1);
+               if (new_set >= 0)
+                       {
+                       options->printer.page_text_position = new_set;
+                       }
+               options->printer.image_text_position = FOOTER_1;
                }
 }
 
-static void print_paper_units_cb(GtkWidget *combo, gpointer data)
+static void image_text_position_f2_cb(GtkWidget *widget, gpointer data)
 {
        PrintWindow *pw = data;
-       PaperUnits units;
+       gint new_set;
 
-       units = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-
-       print_paper_units_set(pw, units);
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               new_set = set_toggle(pw->page_group, FOOTER_2);
+               if (new_set >= 0)
+                       {
+                       options->printer.page_text_position = new_set;
+                       }
+               options->printer.image_text_position = FOOTER_2;
+               }
 }
 
-static GtkWidget *print_paper_orientation_menu(GtkWidget *table, gint column, gint row,
-                                              PaperOrientation preferred,
-                                              GCallback func, gpointer data)
+static void page_text_position_h1_cb(GtkWidget *widget, 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);
+       PrintWindow *pw = data;
+       gint new_set;
 
-       return combo;
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               new_set = set_toggle(pw->image_group, HEADER_1);
+               if (new_set >= 0)
+                       {
+                       options->printer.image_text_position = new_set;
+                       }
+               options->printer.page_text_position = HEADER_1;
+               }
 }
 
-static void print_paper_orientation_cb(GtkWidget *combo, gpointer data)
+static void page_text_position_h2_cb(GtkWidget *widget, gpointer data)
 {
        PrintWindow *pw = data;
-       PaperOrientation o;
-
-       o = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+       gint new_set;
 
-       print_window_layout_set_orientation(pw, o);
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               new_set = set_toggle(pw->image_group, HEADER_2);
+               if (new_set >= 0)
+                       {
+                       options->printer.image_text_position = new_set;
+                       }
+               options->printer.page_text_position = HEADER_2;
+               }
 }
 
-static void print_paper_margin_cb(GtkWidget *spin, gpointer data)
+static void page_text_position_f1_cb(GtkWidget *widget, gpointer data)
 {
        PrintWindow *pw = data;
-       gdouble value;
+       gint new_set;
 
-       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)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
                {
-               pw->margin_bottom = CLAMP(value, 0.0, pw->paper_height);
+               new_set = set_toggle(pw->image_group, FOOTER_1);
+               if (new_set >= 0)
+                       {
+                       options->printer.image_text_position = new_set;
+                       }
+               options->printer.page_text_position = FOOTER_1;
                }
-
-       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)
+static void page_text_position_f2_cb(GtkWidget *widget, gpointer data)
 {
-       GtkWidget *box;
-       GtkWidget *button = NULL;
-       gint i;
-
-       box = pref_group_new(parent_box, FALSE, title, GTK_ORIENTATION_VERTICAL);
+       PrintWindow *pw = data;
+       gint new_set;
 
-       for (i = 0; i < count; i++)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
                {
-               button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(button), _(text[i]));
-               if (i == preferred)
+               new_set = set_toggle(pw->image_group, FOOTER_2);
+               if (new_set >= 0)
                        {
-                       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+                       options->printer.image_text_position = new_set;
                        }
-               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);
+               options->printer.page_text_position = FOOTER_2;
                }
-
-       return box;
 }
 
-static void print_source_select_cb(GtkWidget *widget, gpointer data)
+static void set_print_image_text_string(gchar **template_string, const gchar *value)
 {
-       PrintWindow *pw = data;
+       g_assert(template_string);
 
-       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);
+       g_free(*template_string);
+       *template_string = g_strdup(value);
 }
 
-static void print_layout_select_cb(GtkWidget *widget, gpointer data)
+static void image_text_template_view_changed_cb(GtkWidget *widget, gpointer data)
 {
-       PrintWindow *pw = data;
+       GtkWidget *pTextView;
+       GtkTextBuffer *pTextBuffer;
+       GtkTextIter iStart;
+       GtkTextIter iEnd;
 
-       if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) return;
+       pTextView = GTK_WIDGET(data);
 
-       pw->layout = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "print_layout"));
+       pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
+       gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
+       gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
 
-       print_window_layout_sync_layout(pw);
-       print_window_layout_size(pw);
+       set_print_image_text_string(&options->printer.template_string,
+                                         gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
 }
 
-static void print_image_scale_cb(GtkWidget *spin, gpointer data)
+#define PRE_FORMATTED_COLUMNS 4
+static void print_text_menu(GtkWidget *box, PrintWindow *pw)
 {
-       PrintWindow *pw = data;
-
-       pw->image_scale = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
+       GtkWidget *group;
+       GtkWidget *hbox;
+       GtkWidget *button;
+       GtkWidget *button1;
+       GtkWidget *button2;
+       GtkWidget *image_text_button;
+       GtkWidget *page_text_button;
+       GtkWidget *subgroup;
+       GtkWidget *page_text_view;
+       GtkWidget *image_text_template_view;
+       GtkWidget *scrolled;
+       GtkWidget *scrolled_pre_formatted;
+       GtkTextBuffer *buffer;
+
+       group = pref_group_new(box, FALSE, _("Image text"), GTK_ORIENTATION_VERTICAL);
+
+       image_text_button = pref_checkbox_new_int(group, _("Show image text"),
+                                                                               options->printer.show_image_text, &options->printer.show_image_text);
+
+       subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+
+       pref_checkbox_link_sensitivity(image_text_button, subgroup);
+
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
+
+       /* order is important */
+       button1 = pref_radiobutton_new(hbox, NULL,  "Header 1",
+                                                       options->printer.image_text_position == HEADER_1,
+                                                       G_CALLBACK(image_text_position_h1_cb), pw);
+       button1 = pref_radiobutton_new(hbox, button1,  "Header 2",
+                                                       options->printer.image_text_position == HEADER_2,
+                                                       G_CALLBACK(image_text_position_h2_cb), pw);
+       button1 = pref_radiobutton_new(hbox, button1, "Footer 1",
+                                                       options->printer.image_text_position == FOOTER_1,
+                                                       G_CALLBACK(image_text_position_f1_cb), pw);
+       button1 = pref_radiobutton_new(hbox, button1, "Footer 2",
+                                                       options->printer.image_text_position == FOOTER_2,
+                                                       G_CALLBACK(image_text_position_f2_cb), pw);
+       gtk_widget_show(hbox);
+       pw->image_group = (gtk_radio_button_get_group(GTK_RADIO_BUTTON(button1)));
+
+       image_text_template_view = gtk_text_view_new();
+
+       scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_text_template_view);
+       gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
+       gtk_widget_show(scrolled_pre_formatted);
+       gtk_widget_show(subgroup);
+
+       gtk_widget_set_tooltip_markup(image_text_template_view,
+                                       _("Extensive formatting options are shown in the Help file"));
+
+       scrolled = gtk_scrolled_window_new(NULL, NULL);
+       gtk_widget_set_size_request(scrolled, 200, 50);
+       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+       gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
+       gtk_widget_show(scrolled);
+
+       gtk_container_add(GTK_CONTAINER(scrolled), image_text_template_view);
+       gtk_widget_show(image_text_template_view);
+
+       buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_text_template_view));
+       if (options->printer.template_string) gtk_text_buffer_set_text(buffer, options->printer.template_string, -1);
+       g_signal_connect(G_OBJECT(buffer), "changed",
+                        G_CALLBACK(image_text_template_view_changed_cb), image_text_template_view);
+
+       hbox = pref_box_new(subgroup, 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), "Image text font");
+#else
+       button = gtk_font_button_new();
+       gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image text Font");
+       gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->printer.image_font);
+       g_signal_connect(G_OBJECT(button), "font-set",
+                                G_CALLBACK(print_set_font_cb), "Image text font");
+#endif
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gtk_widget_show(button);
 
-       print_window_layout_set_size(pw, pw->paper_width, pw->paper_height);
+       pref_spacer(group, PREF_PAD_GAP);
+
+       group = pref_group_new(box, FALSE, _("Page text"), GTK_ORIENTATION_VERTICAL);
+
+       page_text_button = pref_checkbox_new_int(group, _("Show page text"),
+                                         options->printer.show_page_text, &options->printer.show_page_text);
+
+       subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+       pref_checkbox_link_sensitivity(page_text_button, subgroup);
+
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(subgroup), hbox, FALSE, FALSE, 0);
+
+       /* order is important */
+       button2 = pref_radiobutton_new(hbox, NULL, "Header 1",
+                                                       options->printer.page_text_position == HEADER_1,
+                                                       G_CALLBACK(page_text_position_h1_cb), pw);
+       button2 = pref_radiobutton_new(hbox, button2,  "Header 2",
+                                                       options->printer.page_text_position == HEADER_2,
+                                                       G_CALLBACK(page_text_position_h2_cb), pw);
+       button2 = pref_radiobutton_new(hbox, button2, "Footer 1",
+                                                       options->printer.page_text_position == FOOTER_1,
+                                                       G_CALLBACK(page_text_position_f1_cb), pw);
+       button2 = pref_radiobutton_new(hbox, button2, "Footer 2",
+                                                       options->printer.page_text_position == FOOTER_2,
+                                                       G_CALLBACK(page_text_position_f2_cb), pw);
+       gtk_widget_show(hbox);
+       pw->page_group = (gtk_radio_button_get_group(GTK_RADIO_BUTTON(button2)));
+
+       scrolled = gtk_scrolled_window_new(NULL, NULL);
+       gtk_widget_set_size_request(scrolled, 50, 50);
+       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+       gtk_box_pack_start(GTK_BOX(subgroup), scrolled, TRUE, TRUE, 5);
+       gtk_widget_show(scrolled);
+
+       page_text_view = gtk_text_view_new();
+       pw->page_text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(page_text_view ));
+       gtk_text_buffer_set_text(GTK_TEXT_BUFFER(pw->page_text), options->printer.page_text, -1);
+       g_object_ref(pw->page_text);
+
+       gtk_widget_set_tooltip_markup(page_text_view, ("Text shown on each page of a single or multi-page print job"));
+       gtk_container_add(GTK_CONTAINER(scrolled), page_text_view);
+       gtk_widget_show(page_text_view);
+
+       hbox = pref_box_new(subgroup, 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), "Page text font");
+#else
+       button = gtk_font_button_new();
+       gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Page text Font");
+       gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->printer.page_font);
+       g_signal_connect(G_OBJECT(button), "font-set",
+                                G_CALLBACK(print_set_font_cb), "Page text font");
+#endif
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gtk_widget_show(button);
 }
 
-static void print_proof_size_cb(GtkWidget *spin, gpointer data)
+static gboolean paginate_cb(GtkPrintOperation *operation,
+                                                                       GtkPrintContext *context,
+                                                                       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)
+       if (pw->job_render_finished)
                {
-               pw->proof_width = value;
+               return TRUE;
                }
        else
                {
-               pw->proof_height = value;
+               return FALSE;
                }
-
-       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)
+gchar *form_image_text(const gchar *template_string, FileData *fd, PrintWindow *pw, gint page_nr, gint total)
 {
-       GtkListStore *store;
-       const gchar *text;
-       GList *list;
-       GList *work;
+       const gchar *name;
+       gchar *text = NULL;
+       GHashTable *vars;
+       gchar *window_title;
+       gchar *delimiter;
+       gchar *collection_name;
 
-       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;
+       if (!fd) return NULL;
 
-               name = work->data;
-               work = work->next;
+       name = fd->name;
 
-               buf = g_strdup_printf(PRINT_LPR_CUSTOM, name);
-               gtk_combo_box_append_text(GTK_COMBO_BOX(combo), buf);
-               g_free(buf);
-               }
-       string_list_free(list);
+       vars = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
 
-       if (pref_list_string_get(PRINT_PREF_GROUP, PRINT_PREF_PRINTERC, &text))
+       window_title = g_strdup(gtk_window_get_title(GTK_WINDOW(pw->parent)));
+       delimiter = g_strstr_len(window_title, -1, " - Collection - ");
+       if (delimiter)
                {
-               gtk_entry_set_text(GTK_ENTRY(pw->custom_entry), text);
+               collection_name = g_strndup(window_title, delimiter - window_title);
                }
        else
                {
-               text = gtk_entry_get_text(GTK_ENTRY(pw->custom_entry));
-               if (!text || strlen(text) == 0)
-                       {
-                       gchar *buf;
+               collection_name = NULL;
+               }
+       g_free(window_title);
 
-                       buf = g_strdup_printf(PRINT_LPR_CUSTOM, _("<printer name>"));
-                       gtk_entry_set_text(GTK_ENTRY(pw->custom_entry), buf);
-                       g_free(buf);
-                       }
+       if (collection_name)
+               {
+               osd_template_insert(vars, "collection", collection_name, OSDT_NONE);
                }
-}
 
-static void print_output_set(PrintWindow *pw, PrintOutput output)
-{
-       gint use_file = FALSE;
-       gint use_custom = FALSE;
-       gint use_format = FALSE;
+       osd_template_insert(vars, "number", g_strdup_printf("%d", page_nr + 1), OSDT_NO_DUP);
+       osd_template_insert(vars, "total", g_strdup_printf("%d", total), OSDT_NO_DUP);
+       osd_template_insert(vars, "name", (gchar *) name, OSDT_NONE);
+       osd_template_insert(vars, "date", fd ? ((gchar *) text_from_time(fd->date)) : "", OSDT_NONE);
+       osd_template_insert(vars, "size", fd ? (text_from_size_abrev(fd->size)) : g_strdup(""), OSDT_FREE);
 
-       pw->output = output;
+       if (fd->pixbuf)
+               {
+               gint w, h;
+               w = gdk_pixbuf_get_width(fd->pixbuf);
+               h = gdk_pixbuf_get_height(fd->pixbuf);
 
-       switch (pw->output)
+               osd_template_insert(vars, "width", g_strdup_printf("%d", w), OSDT_NO_DUP);
+               osd_template_insert(vars, "height", g_strdup_printf("%d", h), OSDT_NO_DUP);
+               osd_template_insert(vars, "res", g_strdup_printf("%d Ã— %d", w, h), OSDT_FREE);
+               }
+       else
                {
-               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;
+               osd_template_insert(vars, "width", NULL, OSDT_NONE);
+               osd_template_insert(vars, "height", NULL, OSDT_NONE);
+               osd_template_insert(vars, "res", NULL, OSDT_NONE);
                }
 
-       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);
+       text = image_osd_mkinfo(template_string, fd, vars);
+       g_hash_table_destroy(vars);
+
+       g_free(collection_name);
+
+       return text;
 }
 
-static void print_output_cb(GtkWidget *combo, gpointer data)
+static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
+                                                                       gint page_nr, gpointer data)
 {
        PrintWindow *pw = data;
-       PrintOutput output;
-
-       output = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+       FileData *fd;
+       cairo_t *cr;
+       gdouble context_width, context_height;
+       gdouble pixbuf_image_width, pixbuf_image_height;
+       gdouble width_offset;
+       gdouble height_offset;
+       GdkPixbuf *pixbuf;
+       GdkPixbuf *rotated = NULL;
+       PangoLayout *layout_image = NULL;
+       PangoLayout *layout_page = NULL;
+       PangoFontDescription *desc;
+       GString *image_text = g_string_new(NULL);
+       GString *page_text = g_string_new(NULL);
+       PangoRectangle ink_rect, logical_rect;
+       gdouble w, h, scale;
+       gdouble image_text_width, image_text_height, page_text_width, page_text_height;
+       gint image_y;
+       gint incr_y;
+       gdouble pango_height;
+       gdouble pango_image_height;
+       gdouble pango_page_height;
+       GtkTextIter start, end;
+       gchar *tmp;
+       gint total;
 
-       print_output_set(pw, output);
-}
+       fd = g_list_nth_data(pw->source_selection, page_nr);
+       total = g_list_length(pw->source_selection);
 
-static GtkWidget *print_output_format_menu(GtkWidget * table, gint column, gint row,
-                                          PrintFileFormat preferred, GCallback func, gpointer data)
-{
-       GtkWidget *combo;
+       pixbuf = g_list_nth_data(pw->print_pixbuf_queue, page_nr);
+       if (fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
+               {
+               rotated = pixbuf_apply_orientation(pixbuf, fd->exif_orientation);
+               pixbuf = rotated;
+               }
 
-       combo = print_combo_menu(print_file_format_text, PRINT_FILE_COUNT, preferred, func, data);
+       pixbuf_image_width = gdk_pixbuf_get_width(pixbuf);
+       pixbuf_image_height = gdk_pixbuf_get_height(pixbuf);
 
-       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);
+       if (options->printer.show_image_text)
+               {
+               image_text = g_string_append(image_text, form_image_text(options->printer.template_string, fd, pw, page_nr, total));
+               }
 
-       return combo;
-}
+       if (options->printer.show_page_text)
+               {
+               gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(pw->page_text), &start, &end);
 
-static void print_output_format_cb(GtkWidget *combo, gpointer data)
-{
-       PrintWindow *pw = data;
+               tmp = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(pw->page_text), &start, &end, FALSE);
+               page_text = g_string_append(page_text, tmp);
 
-       pw->output_format = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
-}
+               g_free(tmp);
+               }
 
-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;
+       cr = gtk_print_context_get_cairo_context(context);
+       context_width = gtk_print_context_get_width(context);
+       context_height = gtk_print_context_get_height(context);
 
-       store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+       pango_image_height = 0;
+       pango_page_height = 0;
+       image_text_width = 0;
+       page_text_width = 0;
 
-       i = 0;
-       while (dpilist[i] != -1)
+       if (image_text->len > 0)
                {
-               GtkTreeIter iter;
-               gchar *text;
+               layout_image = pango_cairo_create_layout(cr);
 
-               if (dpilist[i] == 0)
-                       {
-                       text = g_strdup(_("Unlimited"));
-                       }
-               else
-                       {
-                       text = g_strdup_printf("%d", dpilist[i]);
-                       }
+               pango_layout_set_text(layout_image, image_text->str, -1);
+               desc = pango_font_description_from_string(options->printer.image_font);
+               pango_layout_set_font_description(layout_image, desc);
 
-               gtk_list_store_append(store, &iter);
-               gtk_list_store_set(store, &iter, 0, text, 1, dpilist[i], -1);
-               g_free(text);
+               pango_layout_get_extents(layout_image, &ink_rect, &logical_rect);
+               image_text_width = ((gdouble)logical_rect.width / PANGO_SCALE) ;
+               image_text_height = ((gdouble)logical_rect.height / PANGO_SCALE);
 
-               if (dpi == (gdouble)dpilist[i]) current = i;
+               pango_layout_set_alignment(layout_image, PANGO_ALIGN_CENTER);
+               pango_layout_set_text(layout_image, image_text->str, -1);
 
-               i++;
-               }
+               pango_image_height = image_text_height + PRINT_TEXT_PADDING * 2;
 
-       combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
-       g_object_unref(store);
+               pango_font_description_free(desc);
+               }
 
-       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
-       if (func) g_signal_connect(G_OBJECT(combo), "changed", func, data);
+       if (page_text->len > 0)
+               {
+               layout_page = pango_cairo_create_layout(cr);
 
-       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);
+               pango_layout_set_text(layout_page, page_text->str, -1);
+               desc = pango_font_description_from_string(options->printer.page_font);
+               pango_layout_set_font_description(layout_page, desc);
 
-       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);
+               pango_layout_get_extents(layout_page, &ink_rect, &logical_rect);
+               page_text_width = ((gdouble)logical_rect.width / PANGO_SCALE) ;
+               page_text_height = ((gdouble)logical_rect.height / PANGO_SCALE);
 
-       return combo;
-}
+               pango_layout_set_alignment(layout_page, PANGO_ALIGN_CENTER);
+               pango_layout_set_text(layout_page, page_text->str, -1);
 
-static void print_output_dpi_cb(GtkWidget *combo, gpointer data)
-{
-       PrintWindow *pw = data;
-       GtkTreeModel *store;
-       GtkTreeIter iter;
-       gint n = -1;
+               pango_page_height = page_text_height + PRINT_TEXT_PADDING * 2;
 
-       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);
+               pango_font_description_free(desc);
+               }
 
-       pw->max_dpi = (gdouble)n;
-}
+       pango_height = pango_image_height + pango_page_height;
 
-static void print_text_field_set(PrintWindow *pw, TextInfo field, gint active)
-{
-       if (active)
+       if ((context_width / pixbuf_image_width) < ((context_height - pango_height) / pixbuf_image_height))
                {
-               pw->text_fields |= field;
+               w = context_width;
+               scale = context_width / pixbuf_image_width;
+               h = pixbuf_image_height * scale;
+               height_offset = (context_height - (h + pango_height)) / 2;
+               width_offset = 0;
                }
        else
                {
-               pw->text_fields &= ~field;
+               h = context_height - pango_height ;
+               scale = (context_height - pango_height) / pixbuf_image_height;
+               w = pixbuf_image_width * scale;
+               height_offset = 0;
+               width_offset = (context_width - (pixbuf_image_width * scale)) / 2;
                }
 
-       print_window_layout_render(pw);
-}
+       incr_y = height_offset;
 
-static void print_text_cb_name(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
-       gint active;
+       if (options->printer.page_text_position == HEADER_1 && page_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_page);
 
-       active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-       print_text_field_set(pw, TEXT_INFO_FILENAME, active);
-}
+               incr_y = incr_y + pango_page_height;
+               }
 
-static void print_text_cb_path(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
-       gint active;
+       if (options->printer.image_text_position == HEADER_1 && image_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y + PRINT_TEXT_PADDING);
+               pango_cairo_show_layout(cr, layout_image);
 
-       active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-       print_text_field_set(pw, TEXT_INFO_FILEPATH, active);
-}
+               incr_y = incr_y + pango_image_height;
+               }
 
-static void print_text_cb_date(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
-       gint active;
+       if (options->printer.page_text_position == HEADER_2 && page_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_page);
 
-       active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-       print_text_field_set(pw, TEXT_INFO_FILEDATE, active);
-}
+               incr_y = incr_y + pango_page_height;
+               }
 
-static void print_text_cb_size(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
-       gint active;
+       if (options->printer.image_text_position == HEADER_2 && image_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_image);
 
-       active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-       print_text_field_set(pw, TEXT_INFO_FILESIZE, active);
-}
+               incr_y = incr_y + pango_image_height;
+               }
 
-static void print_text_cb_dims(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
-       gint active;
+       image_y = incr_y;
+       incr_y = incr_y + h;
 
-       active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-       print_text_field_set(pw, TEXT_INFO_DIMENSIONS, active);
-}
+       if (options->printer.page_text_position == FOOTER_1 && page_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y + PRINT_TEXT_PADDING);
+               pango_cairo_show_layout(cr, layout_page);
 
-static void print_text_cb_points(GtkWidget *widget, gpointer data)
-{
-       PrintWindow *pw = data;
+               incr_y = incr_y + pango_page_height;
+               }
 
-       pw->text_points = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
-       print_window_layout_render(pw);
-}
+       if (options->printer.image_text_position == FOOTER_1 && image_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_image);
 
-static void print_text_menu(GtkWidget *box, PrintWindow *pw)
-{
-       GtkWidget *group;
+               incr_y = incr_y + pango_image_height;
+               }
+
+       if (options->printer.page_text_position == FOOTER_2 && page_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (page_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_page);
+
+               incr_y = incr_y + pango_page_height;
+               }
 
-       group = pref_group_new(box, FALSE, _("Show"), GTK_ORIENTATION_VERTICAL);
+       if (options->printer.image_text_position == FOOTER_2 && image_text->len > 0)
+               {
+               cairo_move_to(cr, (w / 2) - (image_text_width / 2) + width_offset, incr_y);
+               pango_cairo_show_layout(cr, layout_image);
+               }
 
-       pref_checkbox_new(group, _("Name"), (pw->text_fields & TEXT_INFO_FILENAME),
-                         G_CALLBACK(print_text_cb_name), pw);
-       pref_checkbox_new(group, _("Path"), (pw->text_fields & TEXT_INFO_FILEPATH),
-                         G_CALLBACK(print_text_cb_path), pw);
-       pref_checkbox_new(group, _("Date"), (pw->text_fields & TEXT_INFO_FILEDATE),
-                         G_CALLBACK(print_text_cb_date), pw);
-       pref_checkbox_new(group, _("Size"), (pw->text_fields & TEXT_INFO_FILESIZE),
-                         G_CALLBACK(print_text_cb_size), pw);
-       pref_checkbox_new(group, _("Dimensions"), (pw->text_fields & TEXT_INFO_DIMENSIONS),
-                         G_CALLBACK(print_text_cb_dims), pw);
+       cairo_scale(cr, scale, scale);
 
-       group = pref_group_new(box, FALSE, _("Font"), GTK_ORIENTATION_VERTICAL);
+       cairo_rectangle(cr,  width_offset * scale , image_y, pixbuf_image_width / scale, pixbuf_image_height / scale);
+       gdk_cairo_set_source_pixbuf(cr, pixbuf, width_offset / scale, image_y / scale);
+       cairo_fill(cr);
 
-       pref_spin_new(group, _("Size:"), _("points"),
-                     8.0, 100.0, 1.0, 0, pw->text_points,
-                     G_CALLBACK(print_text_cb_points), pw);
+       if (image_text->len > 0)
+               {
+               g_object_unref(layout_image);
+               g_string_free(image_text, TRUE);
+               }
+       if (page_text->len > 0)
+               {
+               g_object_unref(layout_page);
+               g_string_free(page_text, TRUE);
+               }
 
-#if 0
-       button = color_selection_new();
-       gtk_box_pack_start(GTK_BOX(group), button, FALSE, FALSE, 0);
-       gtk_widget_show(button);
-#endif
-}
+       if (rotated) g_object_unref(rotated);
 
-/*
- *-----------------------------------------------------------------------------
- * print window
- *-----------------------------------------------------------------------------
- */
+       return;
+}
 
-static void print_window_close(PrintWindow *pw)
+static void begin_print(GtkPrintOperation *operation,
+                                               GtkPrintContext *context,
+                                               gpointer user_data)
 {
-       print_window_layout_render_stop(pw);
+       PrintWindow *pw = user_data;
+       gint page_count;
 
-       generic_dialog_close(pw->dialog);
-       pw->dialog = NULL;
+       page_count = print_layout_page_count(pw);
+       gtk_print_operation_set_n_pages (operation, page_count);
 
-       print_job_close(pw, FALSE);
+       print_job_render_image(pw);
+}
 
-       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);
+GObject *option_tab_cb(GtkPrintOperation *operation, gpointer user_data)
+{
+       PrintWindow *pw = user_data;
 
-       g_free(pw);
+       return G_OBJECT(pw->vbox);
 }
 
-static void print_window_print_cb(GenericDialog *gd, gpointer data)
+static void print_pref_store(PrintWindow *pw)
 {
-       PrintWindow *pw = data;
-
-       switch (pw->output)
-               {
-               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;
-               }
+       gchar *tmp;
+       GtkTextIter start, end;
 
-       print_window_print_start(pw);
+       gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(pw->page_text), &start, &end);
+       tmp = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(pw->page_text), &start, &end, FALSE);
+       g_free(options->printer.page_text);
+       options->printer.page_text = g_strdup(tmp);
+       g_free(tmp);
 }
 
-static void print_window_cancel_cb(GenericDialog *gd, gpointer data)
+static void end_print_cb(GtkPrintOperation *operation,
+                                                               GtkPrintContext *context, gpointer data)
 {
        PrintWindow *pw = data;
+       GList *work;
+       GdkPixbuf *pixbuf;
+       gchar *path;
+       GtkPrintSettings *print_settings;
+       GtkPageSetup *page_setup;
+       GError *error = NULL;
 
-       print_window_close(pw);
-}
+       print_settings = gtk_print_operation_get_print_settings(operation);
+       path = g_build_filename(get_rc_dir(), PRINT_SETTINGS, NULL);
 
-static gint print_pref_int(const gchar *key, gint fallback)
-{
-       gint value;
+       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);
 
-       if (pref_list_int_get(PRINT_PREF_GROUP, key, &value)) return value;
-       return fallback;
-}
+       page_setup = gtk_print_operation_get_default_page_setup(operation);
+       path = g_build_filename(get_rc_dir(), PAGE_SETUP, NULL);
 
-static gdouble print_pref_double(const gchar *key, gdouble fallback)
-{
-       gdouble value;
+       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);
 
-       if (pref_list_double_get(PRINT_PREF_GROUP, key, &value)) return value;
-       return fallback;
+       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_object_unref(pw->page_text);
+       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 = selection;
-       pw->source_list = list;
+       pw->source_selection = file_data_process_groups_in_selection(selection, FALSE, NULL);
 
-       pw->source = PRINT_SOURCE_SELECTION;
-       pw->layout = PRINT_LAYOUT_IMAGE;
-
-       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))
+       if (print_layout_page_count(pw) == 0)
                {
-               pw->paper_width = print_pref_double(PRINT_PREF_CUSTOM_WIDTH, 360.0);
-               pw->paper_height = print_pref_double(PRINT_PREF_CUSTOM_HEIGHT, 720.0);
+               return;
                }
-       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 = TEXT_INFO_FILENAME;
-       pw->text_points = 10;
-       pw->text_r = pw->text_g = pw->text_b = 0;
-
-       pw->save_settings = print_pref_int(PRINT_PREF_SAVE, TRUE);
 
-       {
-       gchar *title = g_strdup_printf("%s - %s", _("Print"), GQ_APPNAME);
-       pw->dialog = file_util_gen_dlg(title, GQ_WMCLASS, "print_dialog",
-                                      parent, FALSE,
-                                      print_window_cancel_cb, pw);
-       g_free(title);
-       }
-
-       geometry.min_width = 32;
-       geometry.min_height = 32;
-       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 */
-
-       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, 100.0,
-                                              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 */
+       pw->parent = parent;
 
        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);
+       pw->vbox = vbox;
 
-       /* paper tab */
+       pw->print_pixbuf_queue = NULL;
+       pw->job_render_finished = FALSE;
+       pw->job_page = 0;
 
-       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);
-
-       print_paper_menu(table, 0, 0, pw->paper_size, G_CALLBACK(print_paper_select_cb), pw);
-
-       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);
-
-       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);
-
-       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);
-
-       /* printer tab */
+       operation = gtk_print_operation_new();
+       settings = gtk_print_settings_new();
 
-       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);
+       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();
+               }
 
-       table = pref_table_new(vbox, 2, 5, FALSE, FALSE);
-       print_output_menu(table, 0, 0, pw->output, G_CALLBACK(print_output_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);
 
-       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);
+       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);
 
-       pref_link_sensitivity(label, combo);
+       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, 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);
+       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);
 
-       pref_link_sensitivity(label, combo);
+       gtk_print_operation_set_n_pages(operation, print_layout_page_count(pw));
 
-       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);
+       gtk_print_operation_run(operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                                                                               GTK_WINDOW (parent), &error);
 
-       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);
+       if (error)
+               {
+               GtkWidget *dialog;
 
-       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: */