]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkprintoperation-win32.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkprintoperation-win32.c
index eb061afb53dda34ecdd551e181965f5621a6bb50..04de8ebbeb178f44d8bd7d2db460199f96162a74 100644 (file)
@@ -13,9 +13,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _MSC_VER
@@ -43,7 +41,6 @@
 #include "gtkstock.h"
 #include "gtk.h"
 #include "gtkwin32embedwidget.h"
-#include "gtkalias.h"
 
 #define MAX_PAGE_RANGES 20
 #define STATUS_POLLING_TIME 2000
@@ -72,7 +69,7 @@ static void win32_poll_status (GtkPrintOperation *op);
 
 static const GUID myIID_IPrintDialogCallback  = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
 
-#ifndef _MSC_VER
+#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
 #undef INTERFACE
 #define INTERFACE IPrintDialogCallback
 DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
@@ -416,6 +413,42 @@ paper_size_to_win32 (GtkPaperSize *paper_size)
   return 0;
 }
 
+static gchar*
+get_default_printer (void)
+{
+  wchar_t *win32_printer_name = NULL;
+  gchar *printer_name = NULL;
+  DWORD needed;
+
+  GetDefaultPrinterW (NULL, &needed);
+  win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
+  if (!GetDefaultPrinterW (win32_printer_name, &needed))
+    {
+      g_free (win32_printer_name);
+      return NULL;
+    }
+  printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
+  g_free (win32_printer_name);
+
+  return printer_name;
+}
+
+static void
+set_hard_margins (GtkPrintOperation *op)
+{
+  double top, bottom, left, right;
+  GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+  top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+  bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
+      - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
+  left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+  right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
+      - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
+
+  _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
+}
+
 void
 win32_start_page (GtkPrintOperation *op,
                  GtkPrintContext *print_context,
@@ -424,6 +457,7 @@ win32_start_page (GtkPrintOperation *op,
   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
   LPDEVMODEW devmode;
   GtkPaperSize *paper_size;
+  double x_off, y_off;
 
   devmode = GlobalLock (op_win32->devmode);
   
@@ -439,6 +473,8 @@ win32_start_page (GtkPrintOperation *op,
     {
       devmode->dmPaperSize = DMPAPER_USER;
       devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
+
+      /* Lengths in DEVMODE are in tenths of a millimeter */
       devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
       devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
     }
@@ -446,6 +482,11 @@ win32_start_page (GtkPrintOperation *op,
   ResetDCW (op_win32->hdc, devmode);
   
   GlobalUnlock (op_win32->devmode);
+
+  set_hard_margins (op);
+  x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
+  y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
+  cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
   
   StartPage (op_win32->hdc);
 }
@@ -455,6 +496,9 @@ win32_end_page (GtkPrintOperation *op,
                GtkPrintContext *print_context)
 {
   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
+
+  cairo_surface_show_page (op_win32->surface);
+
   EndPage (op_win32->hdc);
 }
 
@@ -486,6 +530,8 @@ win32_end_run (GtkPrintOperation *op,
   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
   LPDEVNAMES devnames;
   HANDLE printerHandle = 0;
+
+  cairo_surface_finish (op_win32->surface);
   
   EndDoc (op_win32->hdc);
 
@@ -498,14 +544,13 @@ win32_end_run (GtkPrintOperation *op,
       GlobalUnlock (op_win32->devnames);
     }
   
-  GlobalFree(op_win32->devmode);
-  GlobalFree(op_win32->devnames);
+  GlobalFree (op_win32->devmode);
+  GlobalFree (op_win32->devnames);
 
-  cairo_surface_finish (op_win32->surface);
   cairo_surface_destroy (op_win32->surface);
   op_win32->surface = NULL;
 
-  DeleteDC(op_win32->hdc);
+  DeleteDC (op_win32->hdc);
   
   if (printerHandle != 0)
     {
@@ -608,7 +653,7 @@ static HWND
 get_parent_hwnd (GtkWidget *widget)
 {
   gtk_widget_realize (widget);
-  return gdk_win32_drawable_get_handle (widget->window);
+  return gdk_win32_window_get_handle (gtk_widget_get_window (widget));
 }
 
 static void
@@ -668,10 +713,12 @@ devmode_to_settings (GtkPrintSettings *settings,
                                     -1, NULL, NULL, NULL);
       if (form_name == NULL || form_name[0] == 0)
        form_name = g_strdup (_("Custom size"));
+
+      /* Lengths in DEVMODE are in tenths of a millimeter */
       paper_size = gtk_paper_size_new_custom (form_name,
                                              form_name,
-                                             devmode->dmPaperWidth * 10.0,
-                                             devmode->dmPaperLength * 10.0,
+                                             devmode->dmPaperWidth / 10.0,
+                                             devmode->dmPaperLength / 10.0,
                                              GTK_UNIT_MM);
       gtk_print_settings_set_paper_size (settings, paper_size);
       gtk_paper_size_free (paper_size);
@@ -758,7 +805,7 @@ devmode_to_settings (GtkPrintSettings *settings,
     }
   
   if (devmode->dmFields & DM_COLOR)
-    gtk_print_settings_set_use_color (settings, devmode->dmFields == DMCOLOR_COLOR);
+    gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
   
   if (devmode->dmFields & DM_DUPLEX)
     {
@@ -840,7 +887,7 @@ static void
 dialog_to_print_settings (GtkPrintOperation *op,
                          LPPRINTDLGEXW printdlgex)
 {
-  int i;
+  guint i;
   GtkPrintSettings *settings;
 
   settings = gtk_print_settings_new ();
@@ -912,8 +959,8 @@ devmode_from_settings (GtkPrintSettings *settings,
     {
       devmode->dmDriverExtra = extras_len;
       memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
-      g_free (extras);
     }
+  g_free (extras);
   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
     devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
   
@@ -950,8 +997,10 @@ devmode_from_settings (GtkPrintSettings *settings,
        {
          devmode->dmPaperSize = DMPAPER_USER;
          devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
-         devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) / 10.0;
-         devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) / 10.0;
+
+          /* Lengths in DEVMODE are in tenths of a millimeter */
+         devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
+         devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
        }
       gtk_paper_size_free (paper_size);
     }
@@ -1169,7 +1218,7 @@ dialog_from_print_settings (GtkPrintOperation *op,
   
   printer = gtk_print_settings_get_printer (settings);
   if (printer)
-    printdlgex->hDevNames = gtk_print_win32_devnames_from_printer_name (printer);
+    printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
   
   printdlgex->hDevMode = devmode_from_settings (settings,
                                                op->priv->default_page_setup);
@@ -1288,8 +1337,8 @@ plug_grab_notify (GtkWidget        *widget,
                  gboolean          was_grabbed,
                  GtkPrintOperation *op)
 {
-  EnableWindow(GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
-              was_grabbed);
+  EnableWindow (GetAncestor (GDK_WINDOW_HWND (gtk_widget_get_window (widget)), GA_ROOT),
+               was_grabbed);
 }
 
 
@@ -1307,15 +1356,15 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
       op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
       op_win32 = op->priv->platform_data;
 
-      SetWindowLongPtrW(wnd, GWLP_USERDATA, (LONG_PTR)op);
+      SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
       
-      plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
+      plug = _gtk_win32_embed_widget_new (wnd);
       gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
       op_win32->embed_widget = plug;
       gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
       gtk_widget_show (op->priv->custom_widget);
       gtk_widget_show (plug);
-      gdk_window_focus (plug->window, GDK_CURRENT_TIME);
+      gdk_window_focus (gtk_widget_get_window (plug), GDK_CURRENT_TIME);
 
       /* This dialog is modal, so we grab the embed widget */
       gtk_grab_add (plug);
@@ -1326,7 +1375,7 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
     }
   else if (message == WM_DESTROY)
     {
-      op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
+      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
       op_win32 = op->priv->platform_data;
       
       g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
@@ -1336,7 +1385,7 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
     }
   else 
     {
-      op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
+      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
       op_win32 = op->priv->platform_data;
 
       return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
@@ -1360,29 +1409,30 @@ create_application_page (GtkPrintOperation *op)
   const char *tab_label;
 
   /* Make the template the size of the custom widget size request */
-  gtk_widget_size_request (op->priv->custom_widget, &requisition);
-      
-  base_units = GetDialogBaseUnits();
-  baseunitX = LOWORD(base_units);
-  baseunitY = HIWORD(base_units);
+  gtk_widget_get_preferred_size (op->priv->custom_widget,
+                                 &requisition, NULL);
+
+  base_units = GetDialogBaseUnits ();
+  baseunitX = LOWORD (base_units);
+  baseunitY = HIWORD (base_units);
   
   htemplate = GlobalAlloc (GMEM_MOVEABLE, 
-                          sizeof (DLGTEMPLATE) + sizeof(WORD) * 3);
+                          sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
   template = GlobalLock (htemplate);
   template->style = WS_CHILDWINDOW | DS_CONTROL;
   template->dwExtendedStyle = WS_EX_CONTROLPARENT;
   template->cdit = 0;
-  template->x = MulDiv(0, 4, baseunitX);
-  template->y = MulDiv(0, 8, baseunitY);
-  template->cx = MulDiv(requisition.width, 4, baseunitX);
-  template->cy = MulDiv(requisition.height, 8, baseunitY);
+  template->x = MulDiv (0, 4, baseunitX);
+  template->y = MulDiv (0, 8, baseunitY);
+  template->cx = MulDiv (requisition.width, 4, baseunitX);
+  template->cy = MulDiv (requisition.height, 8, baseunitY);
   
   array = (WORD *) (template+1);
   *array++ = 0; /* menu */
   *array++ = 0; /* class */
   *array++ = 0; /* title */
   
-  memset(&page, 0, sizeof (page));
+  memset (&page, 0, sizeof (page));
   page.dwSize = sizeof (page);
   page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
   page.hInstance = GetModuleHandle (NULL);
@@ -1398,7 +1448,7 @@ create_application_page (GtkPrintOperation *op)
   page.pfnDlgProc = pageDlgProc;
   page.pfnCallback = NULL;
   page.lParam = (LPARAM) op;
-  hpage = CreatePropertySheetPageW(&page);
+  hpage = CreatePropertySheetPageW (&page);
   
   GlobalUnlock (htemplate);
   
@@ -1443,10 +1493,157 @@ create_page_setup (GtkPrintOperation *op)
 }
 
 GtkPrintOperationResult
-_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
-                                                 gboolean show_dialog,
-                                                 GtkWindow *parent,
-                                                 gboolean *do_print)
+gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
+                                       gboolean          *do_print)
+{
+  GtkPrintOperationResult result;
+  GtkPrintOperationWin32 *op_win32;
+  GtkPrintOperationPrivate *priv;
+  GtkPrintSettings *settings;
+  GtkPageSetup *page_setup;
+  DOCINFOW docinfo;
+  HGLOBAL hDevMode = NULL;
+  HGLOBAL hDevNames = NULL;
+  HDC hDC = NULL;
+  const char *printer = NULL;
+  double dpi_x, dpi_y;
+  int job_id;
+  cairo_t *cr;
+  DEVNAMES *pdn;
+  DEVMODEW *pdm;
+
+  *do_print = FALSE;
+
+  priv = op->priv;
+  settings = priv->print_settings;
+  
+  op_win32 = g_new0 (GtkPrintOperationWin32, 1);
+  priv->platform_data = op_win32;
+  priv->free_platform_data = (GDestroyNotify) op_win32_free;
+  printer = gtk_print_settings_get_printer (settings);
+
+  if (!printer)
+    {
+      /* No printer selected. Get the system default printer and store
+       * it in settings.
+       */
+      gchar *tmp_printer = get_default_printer ();
+      if (!tmp_printer)
+       {
+         result = GTK_PRINT_OPERATION_RESULT_ERROR;
+         g_set_error_literal (&priv->error,
+                              GTK_PRINT_ERROR,
+                              GTK_PRINT_ERROR_INTERNAL_ERROR,
+                              _("No printer found"));
+         goto out;
+       }
+      gtk_print_settings_set_printer (settings, tmp_printer);
+      printer = gtk_print_settings_get_printer (settings);
+      g_free (tmp_printer);
+    }
+
+  hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
+  hDevMode = devmode_from_settings (settings, op->priv->default_page_setup);
+
+  /* Create a printer DC for the print settings and page setup provided. */
+  pdn = GlobalLock (hDevNames);
+  pdm = GlobalLock (hDevMode);
+  hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
+                  (wchar_t*)pdn + pdn->wDeviceOffset,
+                  (wchar_t*)pdn + pdn->wOutputOffset,
+                  pdm );
+  GlobalUnlock (hDevNames);
+  GlobalUnlock (hDevMode);
+
+  if (!hDC)
+    {
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                          GTK_PRINT_ERROR,
+                          GTK_PRINT_ERROR_INTERNAL_ERROR,
+                          _("Invalid argument to CreateDC"));
+      goto out;
+    }
+  
+  priv->print_context = _gtk_print_context_new (op);
+  page_setup = create_page_setup (op);
+  _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+  g_object_unref (page_setup);
+
+  *do_print = TRUE;
+
+  op_win32->surface = cairo_win32_printing_surface_create (hDC);
+  dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
+  dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
+
+  cr = cairo_create (op_win32->surface);
+  gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+  cairo_destroy (cr);
+
+  set_hard_margins (op);
+
+  memset (&docinfo, 0, sizeof (DOCINFOW));
+  docinfo.cbSize = sizeof (DOCINFOW); 
+  docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
+  docinfo.lpszOutput = NULL; 
+  docinfo.lpszDatatype = NULL; 
+  docinfo.fwType = 0; 
+
+  job_id = StartDocW (hDC, &docinfo); 
+  g_free ((void *)docinfo.lpszDocName);
+  if (job_id <= 0)
+    { 
+      result = GTK_PRINT_OPERATION_RESULT_ERROR;
+      g_set_error_literal (&priv->error,
+                          GTK_PRINT_ERROR,
+                          GTK_PRINT_ERROR_GENERAL,
+                          _("Error from StartDoc"));
+      *do_print = FALSE;
+      cairo_surface_destroy (op_win32->surface);
+      op_win32->surface = NULL;
+      goto out; 
+    }
+
+  result = GTK_PRINT_OPERATION_RESULT_APPLY;
+  op_win32->hdc = hDC;
+  op_win32->devmode = hDevMode;
+  op_win32->devnames = hDevNames;
+  op_win32->job_id = job_id;
+  op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
+  op->priv->num_page_ranges = 0;
+  if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
+    op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
+                                                               &op->priv->num_page_ranges);
+  op->priv->manual_num_copies = 1;
+  op->priv->manual_collation = FALSE;
+  op->priv->manual_reverse = FALSE;
+  op->priv->manual_orientation = FALSE;
+  op->priv->manual_scale = 1.0;
+  op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+  op->priv->manual_number_up = 1;
+  op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
+
+  op->priv->start_page = win32_start_page;
+  op->priv->end_page = win32_end_page;
+  op->priv->end_run = win32_end_run;
+  
+ out:
+  if (!*do_print && hDC != NULL)
+    DeleteDC (hDC);
+
+  if (!*do_print && hDevMode != NULL)
+    GlobalFree (hDevMode);
+
+  if (!*do_print && hDevNames != NULL)
+    GlobalFree (hDevNames);
+
+  return result;
+}
+
+GtkPrintOperationResult
+gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
+                                    GtkWindow         *parent,
+                                    gboolean          *do_print)
 {
   HRESULT hResult;
   LPPRINTDLGEXW printdlgex = NULL;
@@ -1479,14 +1676,14 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   if (!printdlgex)
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error (&priv->error,
-                  GTK_PRINT_ERROR,
-                  GTK_PRINT_ERROR_NOMEM,
-                  _("Not enough free memory"));
+      g_set_error_literal (&priv->error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_NOMEM,
+                           _("Not enough free memory"));
       goto out;
     }      
 
-  printdlgex->lStructSize = sizeof(PRINTDLGEXW);
+  printdlgex->lStructSize = sizeof (PRINTDLGEXW);
   printdlgex->hwndOwner = parentHWnd;
   printdlgex->hDevMode = NULL;
   printdlgex->hDevNames = NULL;
@@ -1502,10 +1699,10 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   if (!page_ranges) 
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error (&priv->error,
-                  GTK_PRINT_ERROR,
-                  GTK_PRINT_ERROR_NOMEM,
-                  _("Not enough free memory"));
+      g_set_error_literal (&priv->error,
+                           GTK_PRINT_ERROR,
+                           GTK_PRINT_ERROR_NOMEM,
+                           _("Not enough free memory"));
       goto out;
     }
 
@@ -1542,7 +1739,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   printdlgex->lpCallback = (IUnknown *)callback;
   got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
 
-  hResult = PrintDlgExW(printdlgex);
+  hResult = PrintDlgExW (printdlgex);
   IUnknown_Release ((IUnknown *)callback);
   gdk_win32_set_modal_dialog_libgtk_only (NULL);
 
@@ -1550,30 +1747,30 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
       if (hResult == E_OUTOFMEMORY)
-       g_set_error (&priv->error,
-                    GTK_PRINT_ERROR,
-                    GTK_PRINT_ERROR_NOMEM,
-                    _("Not enough free memory"));
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_NOMEM,
+                             _("Not enough free memory"));
       else if (hResult == E_INVALIDARG)
-       g_set_error (&priv->error,
-                    GTK_PRINT_ERROR,
-                    GTK_PRINT_ERROR_INTERNAL_ERROR,
-                    _("Invalid argument to PrintDlgEx"));
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid argument to PrintDlgEx"));
       else if (hResult == E_POINTER)
-       g_set_error (&priv->error,
-                    GTK_PRINT_ERROR,
-                    GTK_PRINT_ERROR_INTERNAL_ERROR,
-                    _("Invalid pointer to PrintDlgEx"));
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid pointer to PrintDlgEx"));
       else if (hResult == E_HANDLE)
-       g_set_error (&priv->error,
-                    GTK_PRINT_ERROR,
-                    GTK_PRINT_ERROR_INTERNAL_ERROR,
-                    _("Invalid handle to PrintDlgEx"));
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_INTERNAL_ERROR,
+                             _("Invalid handle to PrintDlgEx"));
       else /* E_FAIL */
-       g_set_error (&priv->error,
-                    GTK_PRINT_ERROR,
-                    GTK_PRINT_ERROR_GENERAL,
-                    _("Unspecified error"));
+       g_set_error_literal (&priv->error,
+                             GTK_PRINT_ERROR,
+                             GTK_PRINT_ERROR_GENERAL,
+                             _("Unspecified error"));
       goto out;
     }
 
@@ -1601,30 +1798,33 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
       
       *do_print = TRUE;
 
-      op_win32->surface = cairo_win32_surface_create (printdlgex->hDC);
+      op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
+
       dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
       dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
 
       cr = cairo_create (op_win32->surface);
       gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
       cairo_destroy (cr);
-      
-      memset( &docinfo, 0, sizeof (DOCINFOW));
+
+      set_hard_margins (op);
+
+      memset ( &docinfo, 0, sizeof (DOCINFOW));
       docinfo.cbSize = sizeof (DOCINFOW); 
       docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
       docinfo.lpszOutput = (LPCWSTR) NULL; 
       docinfo.lpszDatatype = (LPCWSTR) NULL; 
       docinfo.fwType = 0; 
 
-      job_id = StartDocW(printdlgex->hDC, &docinfo); 
+      job_id = StartDocW (printdlgex->hDC, &docinfo); 
       g_free ((void *)docinfo.lpszDocName);
       if (job_id <= 0) 
-       { 
+       {
          result = GTK_PRINT_OPERATION_RESULT_ERROR;
-         g_set_error (&priv->error,
-                      GTK_PRINT_ERROR,
-                      GTK_PRINT_ERROR_GENERAL,
-                    _("Error from StartDoc"));
+         g_set_error_literal (&priv->error,
+                               GTK_PRINT_ERROR,
+                               GTK_PRINT_ERROR_GENERAL,
+                               _("Error from StartDoc"));
          *do_print = FALSE;
          cairo_surface_destroy (op_win32->surface);
          op_win32->surface = NULL;
@@ -1647,6 +1847,8 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
       op->priv->manual_orientation = FALSE;
       op->priv->manual_scale = 1.0;
       op->priv->manual_page_set = GTK_PAGE_SET_ALL;
+      op->priv->manual_number_up = 1;
+      op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
     }
 
   op->priv->start_page = win32_start_page;
@@ -1654,11 +1856,14 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   op->priv->end_run = win32_end_run;
   
   out:
+  if (!*do_print && printdlgex && printdlgex->hDC != NULL)
+    DeleteDC (printdlgex->hDC);
+
   if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) 
-    GlobalFree(printdlgex->hDevMode); 
+    GlobalFree (printdlgex->hDevMode); 
 
   if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) 
-    GlobalFree(printdlgex->hDevNames); 
+    GlobalFree (printdlgex->hDevNames); 
 
   if (page_ranges)
     GlobalFree (page_ranges);
@@ -1672,6 +1877,18 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   return result;
 }
 
+GtkPrintOperationResult
+_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+                                                 gboolean           show_dialog,
+                                                 GtkWindow         *parent,
+                                                 gboolean          *do_print)
+{
+  if (show_dialog)
+    return gtk_print_operation_run_with_dialog (op, parent, do_print);
+  else
+    return gtk_print_operation_run_without_dialog (op, do_print);
+}
+
 void
 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
                                                      cairo_surface_t   *surface,
@@ -1703,10 +1920,13 @@ _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
                                                        cairo_surface_t *surface,
                                                        cairo_t *cr)
 {
-  /* TODO: This doesn't actually seem to work.
-   * Do enhanced metafiles really support multiple pages?
+  HDC dc;
+
+  cairo_surface_show_page (surface);
+
+  /* TODO: Enhanced metafiles don't support multiple pages.
    */
-  HDC dc = cairo_win32_surface_get_dc (surface);
+  dc = cairo_win32_surface_get_dc (surface);
   EndPage (dc);
 }
 
@@ -1718,7 +1938,6 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
                                                              gchar            **target)
 {
   GtkPaperSize *paper_size;
-  double w, h;
   HDC metafile_dc;
   RECT rect;
   char *template;
@@ -1728,7 +1947,7 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
 
   template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
   fd = g_mkstemp (template);
-  close(fd);
+  close (fd);
 
   filename = g_strconcat (template, ".emf", NULL);
   g_free (template);
@@ -1737,13 +1956,12 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
   g_free (filename);
 
   paper_size = gtk_page_setup_get_paper_size (page_setup);
-  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
-  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
-  
+
+  /* The rectangle dimensions are given in hundredths of a millimeter */
   rect.left = 0;
-  rect.right = w*100;
+  rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
   rect.top = 0;
-  rect.bottom = h*100;
+  rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
   
   metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
                                    &rect, L"Gtk+\0Print Preview\0\0");
@@ -1758,7 +1976,7 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
   *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
   *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
 
-  return cairo_win32_surface_create (metafile_dc);
+  return cairo_win32_printing_surface_create (metafile_dc);
 }
 
 void
@@ -1796,7 +2014,7 @@ gtk_print_run_page_setup_dialog (GtkWindow        *parent,
   
   memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
 
-  pagesetupdlg->lStructSize = sizeof(PAGESETUPDLGW);
+  pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
 
   if (parent != NULL)
     pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
@@ -1808,10 +2026,10 @@ gtk_print_run_page_setup_dialog (GtkWindow        *parent,
   pagesetupdlg->hDevNames = NULL;
   printer = gtk_print_settings_get_printer (settings);
   if (printer)
-    pagesetupdlg->hDevNames = gtk_print_win32_devnames_from_printer_name (printer);
+    pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
 
-  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
-                (LPWSTR)&measure_system, sizeof (DWORD));
+  GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
+                 (LPWSTR)&measure_system, sizeof (DWORD));
 
   if (measure_system == 0)
     {
@@ -1859,9 +2077,6 @@ gtk_print_run_page_setup_dialog (GtkWindow        *parent,
        devmode_to_settings (settings, pagesetupdlg->hDevMode);
     }
   
-  if (free_settings)
-    g_object_unref (settings);
-
   if (res)
     {
       gtk_page_setup_set_orientation (page_setup, 
@@ -1898,6 +2113,9 @@ gtk_print_run_page_setup_dialog (GtkWindow        *parent,
                                        unit);
     }
   
+  if (free_settings)
+    g_object_unref (settings);
+
   return page_setup;
 }
 
@@ -1914,6 +2132,3 @@ gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
   done_cb (new_page_setup, data);
   g_object_unref (new_page_setup);
 }
-
-#define __GTK_PRINT_OPERATION_WIN32_C__
-#include "gtkaliasdef.c"