]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintoperation-win32.c
Revert "Set win32 printer hard margins on print context"
[~andy/gtk] / gtk / gtkprintoperation-win32.c
1 /* GTK - The GIMP Toolkit
2  * gtkprintoperation-win32.c: Print Operation Details for Win32
3  * Copyright (C) 2006, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifndef _MSC_VER
22 #define _WIN32_WINNT 0x0500
23 #define WINVER _WIN32_WINNT
24 #endif
25
26 #define COBJMACROS
27 #include "config.h"
28 #include <math.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <io.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <windows.h>
36 #include <cairo-win32.h>
37 #include <glib.h>
38 #include "gtkprintoperation-private.h"
39 #include "gtkprint-win32.h"
40 #include "gtkintl.h"
41 #include "gtkinvisible.h"
42 #include "gtkplug.h"
43 #include "gtkstock.h"
44 #include "gtk.h"
45 #include "gtkwin32embedwidget.h"
46 #include "gtkalias.h"
47
48 #define MAX_PAGE_RANGES 20
49 #define STATUS_POLLING_TIME 2000
50
51 #ifndef JOB_STATUS_RESTART
52 #define JOB_STATUS_RESTART 0x800
53 #endif
54
55 #ifndef JOB_STATUS_COMPLETE
56 #define JOB_STATUS_COMPLETE 0x1000
57 #endif
58
59 typedef struct {
60   HDC hdc;
61   HGLOBAL devmode;
62   HGLOBAL devnames;
63   HANDLE printerHandle;
64   int job_id;
65   guint timeout_id;
66
67   cairo_surface_t *surface;
68   GtkWidget *embed_widget;
69 } GtkPrintOperationWin32;
70
71 static void win32_poll_status (GtkPrintOperation *op);
72
73 static const GUID myIID_IPrintDialogCallback  = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
74
75 #if !defined (_MSC_VER) && !defined (MINGW64) && !defined (__MINGW64)
76 #undef INTERFACE
77 #define INTERFACE IPrintDialogCallback
78 DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
79 {
80     STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
81     STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
82     STDMETHOD_ (ULONG, Release)(THIS) PURE;
83     STDMETHOD (InitDone)(THIS) PURE;
84     STDMETHOD (SelectionChange)(THIS) PURE;
85     STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
86 }; 
87 #endif
88
89 static UINT got_gdk_events_message;
90
91 UINT_PTR CALLBACK
92 run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
93 {
94   if (uiMsg == WM_INITDIALOG)
95     {
96       gdk_win32_set_modal_dialog_libgtk_only (hdlg);
97       while (gtk_events_pending ())
98         gtk_main_iteration ();
99     }
100   else if (uiMsg == got_gdk_events_message)
101     {
102       while (gtk_events_pending ())
103         gtk_main_iteration ();
104       return 1;
105     }
106   return 0;
107 }
108
109 static GtkPageOrientation
110 orientation_from_win32 (short orientation)
111 {
112   if (orientation == DMORIENT_LANDSCAPE)
113     return GTK_PAGE_ORIENTATION_LANDSCAPE;
114   return GTK_PAGE_ORIENTATION_PORTRAIT;
115 }
116
117 static short
118 orientation_to_win32 (GtkPageOrientation orientation)
119 {
120   if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
121       orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
122     return DMORIENT_LANDSCAPE;
123   return DMORIENT_PORTRAIT;
124 }
125
126 static GtkPaperSize *
127 paper_size_from_win32 (short size)
128 {
129   const char *name;
130   
131   switch (size)
132     {
133     case DMPAPER_LETTER_TRANSVERSE:
134     case DMPAPER_LETTER:
135     case DMPAPER_LETTERSMALL:
136       name = "na_letter";
137       break;
138     case DMPAPER_TABLOID:
139     case DMPAPER_LEDGER:
140       name = "na_ledger";
141       break;
142     case DMPAPER_LEGAL:
143       name = "na_legal";
144       break;
145     case DMPAPER_STATEMENT:
146       name = "na_invoice";
147       break;
148     case DMPAPER_EXECUTIVE:
149       name = "na_executive";
150       break;
151     case DMPAPER_A3:
152     case DMPAPER_A3_TRANSVERSE:
153       name = "iso_a3";
154       break;
155     case DMPAPER_A4:
156     case DMPAPER_A4SMALL:
157     case DMPAPER_A4_TRANSVERSE:
158       name = "iso_a4";
159       break;
160     case DMPAPER_A5:
161     case DMPAPER_A5_TRANSVERSE:
162       name = "iso_a5";
163       break;
164     case DMPAPER_B4:
165       name = "jis_b4";
166       break;
167     case DMPAPER_B5:
168     case DMPAPER_B5_TRANSVERSE:
169       name = "jis_b5";
170       break;
171     case DMPAPER_QUARTO:
172       name = "na_quarto";
173       break;
174     case DMPAPER_10X14:
175       name = "na_10x14";
176       break;
177     case DMPAPER_11X17:
178       name = "na_ledger";
179       break;
180     case DMPAPER_NOTE:
181       name = "na_letter";
182       break;
183     case DMPAPER_ENV_9:
184       name = "na_number-9";
185       break;
186     case DMPAPER_ENV_10:
187       name = "na_number-10";
188       break;
189     case DMPAPER_ENV_11:
190       name = "na_number-11";
191       break;
192     case DMPAPER_ENV_12:
193       name = "na_number-12";
194       break;
195     case DMPAPER_ENV_14:
196       name = "na_number-14";
197       break;
198     case DMPAPER_CSHEET:
199       name = "na_c";
200       break;
201     case DMPAPER_DSHEET:
202       name = "na_d";
203       break;
204     case DMPAPER_ESHEET:
205       name = "na_e";
206       break;
207     case DMPAPER_ENV_DL:
208       name = "iso_dl";
209       break;
210     case DMPAPER_ENV_C5:
211       name = "iso_c5";
212       break;
213     case DMPAPER_ENV_C3:
214       name = "iso_c3";
215       break;
216     case DMPAPER_ENV_C4:
217       name = "iso_c4";
218       break;
219     case DMPAPER_ENV_C6:
220       name = "iso_c6";
221       break;
222     case DMPAPER_ENV_C65:
223       name = "iso_c6c5";
224       break;
225     case DMPAPER_ENV_B4:
226       name = "iso_b4";
227       break;
228     case DMPAPER_ENV_B5:
229       name = "iso_b5";
230       break;
231     case DMPAPER_ENV_B6:
232       name = "iso_b6";
233       break;
234     case DMPAPER_ENV_ITALY:
235       name = "om_italian";
236       break;
237     case DMPAPER_ENV_MONARCH:
238       name = "na_monarch";
239       break;
240     case DMPAPER_ENV_PERSONAL:
241       name = "na_personal";
242       break;
243     case DMPAPER_FANFOLD_US:
244       name = "na_fanfold-us";
245       break;
246     case DMPAPER_FANFOLD_STD_GERMAN:
247       name = "na_fanfold-eur";
248       break;
249     case DMPAPER_FANFOLD_LGL_GERMAN:
250       name = "na_foolscap";
251       break;
252     case DMPAPER_ISO_B4:
253       name = "iso_b4";
254       break;
255     case DMPAPER_JAPANESE_POSTCARD:
256       name = "jpn_hagaki";
257       break;
258     case DMPAPER_9X11:
259       name = "na_9x11";
260       break;
261     case DMPAPER_10X11:
262       name = "na_10x11";
263       break;
264     case DMPAPER_ENV_INVITE:
265       name = "om_invite";
266        break;
267     case DMPAPER_LETTER_EXTRA:
268     case DMPAPER_LETTER_EXTRA_TRANSVERSE:
269       name = "na_letter-extra";
270       break;
271     case DMPAPER_LEGAL_EXTRA:
272       name = "na_legal-extra";
273       break;
274     case DMPAPER_TABLOID_EXTRA:
275       name = "na_arch";
276       break;
277     case DMPAPER_A4_EXTRA:
278       name = "iso_a4-extra";
279       break;
280     case DMPAPER_B_PLUS:
281       name = "na_b-plus";
282       break;
283     case DMPAPER_LETTER_PLUS:
284       name = "na_letter-plus";
285       break;
286     case DMPAPER_A3_EXTRA:
287     case DMPAPER_A3_EXTRA_TRANSVERSE:
288       name = "iso_a3-extra";
289       break;
290     case DMPAPER_A5_EXTRA:
291       name = "iso_a5-extra";
292       break;
293     case DMPAPER_B5_EXTRA:
294       name = "iso_b5-extra";
295       break;
296     case DMPAPER_A2:
297       name = "iso_a2";
298       break;
299       
300     default:
301       name = NULL;
302       break;
303     }
304
305   if (name)
306     return gtk_paper_size_new (name);
307   else 
308     return NULL;
309 }
310
311 static short
312 paper_size_to_win32 (GtkPaperSize *paper_size)
313 {
314   const char *format;
315
316   if (gtk_paper_size_is_custom (paper_size))
317     return 0;
318   
319   format = gtk_paper_size_get_name (paper_size);
320
321   if (strcmp (format, "na_letter") == 0)
322     return DMPAPER_LETTER;
323   if (strcmp (format, "na_ledger") == 0)
324     return DMPAPER_LEDGER;
325   if (strcmp (format, "na_legal") == 0)
326     return DMPAPER_LEGAL;
327   if (strcmp (format, "na_invoice") == 0)
328     return DMPAPER_STATEMENT;
329   if (strcmp (format, "na_executive") == 0)
330     return DMPAPER_EXECUTIVE;
331   if (strcmp (format, "iso_a2") == 0)
332     return DMPAPER_A2;
333   if (strcmp (format, "iso_a3") == 0)
334     return DMPAPER_A3;
335   if (strcmp (format, "iso_a4") == 0)
336     return DMPAPER_A4;
337   if (strcmp (format, "iso_a5") == 0)
338     return DMPAPER_A5;
339   if (strcmp (format, "iso_b4") == 0)
340     return DMPAPER_B4;
341   if (strcmp (format, "iso_b5") == 0)
342     return DMPAPER_B5;
343   if (strcmp (format, "na_quarto") == 0)
344     return DMPAPER_QUARTO;
345   if (strcmp (format, "na_10x14") == 0)
346     return DMPAPER_10X14;
347   if (strcmp (format, "na_number-9") == 0)
348     return DMPAPER_ENV_9;
349   if (strcmp (format, "na_number-10") == 0)
350     return DMPAPER_ENV_10;
351   if (strcmp (format, "na_number-11") == 0)
352     return DMPAPER_ENV_11;
353   if (strcmp (format, "na_number-12") == 0)
354     return DMPAPER_ENV_12;
355   if (strcmp (format, "na_number-14") == 0)
356     return DMPAPER_ENV_14;
357   if (strcmp (format, "na_c") == 0)
358     return DMPAPER_CSHEET;
359   if (strcmp (format, "na_d") == 0)
360     return DMPAPER_DSHEET;
361   if (strcmp (format, "na_e") == 0)
362     return DMPAPER_ESHEET;
363   if (strcmp (format, "iso_dl") == 0)
364     return DMPAPER_ENV_DL;
365   if (strcmp (format, "iso_c3") == 0)
366     return DMPAPER_ENV_C3;
367   if (strcmp (format, "iso_c4") == 0)
368     return DMPAPER_ENV_C4;
369   if (strcmp (format, "iso_c5") == 0)
370     return DMPAPER_ENV_C5;
371   if (strcmp (format, "iso_c6") == 0)
372     return DMPAPER_ENV_C6;
373   if (strcmp (format, "iso_c5c6") == 0)
374     return DMPAPER_ENV_C65;
375   if (strcmp (format, "iso_b6") == 0)
376     return DMPAPER_ENV_B6;
377   if (strcmp (format, "om_italian") == 0)
378     return DMPAPER_ENV_ITALY;
379   if (strcmp (format, "na_monarch") == 0)
380     return DMPAPER_ENV_MONARCH;
381   if (strcmp (format, "na_personal") == 0)
382     return DMPAPER_ENV_PERSONAL;
383   if (strcmp (format, "na_fanfold-us") == 0)
384     return DMPAPER_FANFOLD_US;
385   if (strcmp (format, "na_fanfold-eur") == 0)
386     return DMPAPER_FANFOLD_STD_GERMAN;
387   if (strcmp (format, "na_foolscap") == 0)
388     return DMPAPER_FANFOLD_LGL_GERMAN;
389   if (strcmp (format, "jpn_hagaki") == 0)
390     return DMPAPER_JAPANESE_POSTCARD;
391   if (strcmp (format, "na_9x11") == 0)
392     return DMPAPER_9X11;
393   if (strcmp (format, "na_10x11") == 0)
394     return DMPAPER_10X11;
395   if (strcmp (format, "om_invite") == 0)
396     return DMPAPER_ENV_INVITE;
397   if (strcmp (format, "na_letter-extra") == 0)
398     return DMPAPER_LETTER_EXTRA;
399   if (strcmp (format, "na_legal-extra") == 0)
400     return DMPAPER_LEGAL_EXTRA;
401   if (strcmp (format, "na_arch") == 0)
402     return DMPAPER_TABLOID_EXTRA;
403   if (strcmp (format, "iso_a3-extra") == 0)
404     return DMPAPER_A3_EXTRA;
405   if (strcmp (format, "iso_a4-extra") == 0)
406     return DMPAPER_A4_EXTRA;
407   if (strcmp (format, "iso_a5-extra") == 0)
408     return DMPAPER_A5_EXTRA;
409   if (strcmp (format, "iso_b5-extra") == 0)
410     return DMPAPER_B5_EXTRA;
411   if (strcmp (format, "na_b-plus") == 0)
412     return DMPAPER_B_PLUS;
413   if (strcmp (format, "na_letter-plus") == 0)
414     return DMPAPER_LETTER_PLUS;
415
416   return 0;
417 }
418
419 static gchar*
420 get_default_printer (void)
421 {
422   wchar_t *win32_printer_name = NULL;
423   gchar *printer_name = NULL;
424   DWORD needed;
425
426   GetDefaultPrinterW (NULL, &needed);
427   win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
428   if (!GetDefaultPrinterW (win32_printer_name, &needed))
429     {
430       g_free (win32_printer_name);
431       return NULL;
432     }
433   printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
434   g_free (win32_printer_name);
435
436   return printer_name;
437 }
438
439 void
440 win32_start_page (GtkPrintOperation *op,
441                   GtkPrintContext *print_context,
442                   GtkPageSetup *page_setup)
443 {
444   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
445   LPDEVMODEW devmode;
446   GtkPaperSize *paper_size;
447   double x_off, y_off;
448
449   devmode = GlobalLock (op_win32->devmode);
450   
451   devmode->dmFields |= DM_ORIENTATION;
452   devmode->dmOrientation =
453     orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
454   
455   paper_size = gtk_page_setup_get_paper_size (page_setup);
456   devmode->dmFields |= DM_PAPERSIZE;
457   devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
458   devmode->dmPaperSize = paper_size_to_win32 (paper_size);
459   if (devmode->dmPaperSize == 0)
460     {
461       devmode->dmPaperSize = DMPAPER_USER;
462       devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
463
464       /* Lengths in DEVMODE are in tenths of a millimeter */
465       devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
466       devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
467     }
468   
469   ResetDCW (op_win32->hdc, devmode);
470   
471   GlobalUnlock (op_win32->devmode);
472
473   x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
474   y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
475   cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
476   
477   StartPage (op_win32->hdc);
478 }
479
480 static void
481 win32_end_page (GtkPrintOperation *op,
482                 GtkPrintContext *print_context)
483 {
484   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
485
486   cairo_surface_show_page (op_win32->surface);
487
488   EndPage (op_win32->hdc);
489 }
490
491 static gboolean
492 win32_poll_status_timeout (GtkPrintOperation *op)
493 {
494   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
495   
496   op_win32->timeout_id = 0;
497   /* We need to ref this, as setting the status to finished
498      might unref the object */
499   g_object_ref (op);
500   win32_poll_status (op);
501
502   if (!gtk_print_operation_is_finished (op))
503     op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
504                                           (GSourceFunc)win32_poll_status_timeout,
505                                           op);
506   g_object_unref (op);
507   return FALSE;
508 }
509
510
511 static void
512 win32_end_run (GtkPrintOperation *op,
513                gboolean           wait,
514                gboolean           cancelled)
515 {
516   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
517   LPDEVNAMES devnames;
518   HANDLE printerHandle = 0;
519
520   cairo_surface_finish (op_win32->surface);
521   
522   EndDoc (op_win32->hdc);
523
524   if (op->priv->track_print_status)
525     {
526       devnames = GlobalLock (op_win32->devnames);
527       if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
528                          &printerHandle, NULL))
529         printerHandle = 0;
530       GlobalUnlock (op_win32->devnames);
531     }
532   
533   GlobalFree (op_win32->devmode);
534   GlobalFree (op_win32->devnames);
535
536   cairo_surface_destroy (op_win32->surface);
537   op_win32->surface = NULL;
538
539   DeleteDC (op_win32->hdc);
540   
541   if (printerHandle != 0)
542     {
543       op_win32->printerHandle = printerHandle;
544       win32_poll_status (op);
545       op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
546                                             (GSourceFunc)win32_poll_status_timeout,
547                                             op);
548     }
549   else
550     /* Dunno what happened, pretend its finished */
551     _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
552 }
553
554 static void
555 win32_poll_status (GtkPrintOperation *op)
556 {
557   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
558   guchar *data;
559   DWORD needed;
560   JOB_INFO_1W *job_info;
561   GtkPrintStatus status;
562   char *status_str;
563   BOOL ret;
564
565   GetJobW (op_win32->printerHandle, op_win32->job_id,
566            1,(LPBYTE)NULL, 0, &needed);
567   data = g_malloc (needed);
568   ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
569                  1, (LPBYTE)data, needed, &needed);
570
571   status_str = NULL;
572   if (ret)
573     {
574       DWORD win32_status;
575       job_info = (JOB_INFO_1W *)data;
576       win32_status = job_info->Status;
577
578       if (job_info->pStatus)
579         status_str = g_utf16_to_utf8 (job_info->pStatus, 
580                                       -1, NULL, NULL, NULL);
581      
582       if (win32_status &
583           (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
584         status = GTK_PRINT_STATUS_FINISHED;
585       else if (win32_status &
586                (JOB_STATUS_OFFLINE |
587                 JOB_STATUS_PAPEROUT |
588                 JOB_STATUS_PAUSED |
589                 JOB_STATUS_USER_INTERVENTION))
590         {
591           status = GTK_PRINT_STATUS_PENDING_ISSUE;
592           if (status_str == NULL)
593             {
594               if (win32_status & JOB_STATUS_OFFLINE)
595                 status_str = g_strdup (_("Printer offline"));
596               else if (win32_status & JOB_STATUS_PAPEROUT)
597                 status_str = g_strdup (_("Out of paper"));
598               else if (win32_status & JOB_STATUS_PAUSED)
599                 status_str = g_strdup (_("Paused"));
600               else if (win32_status & JOB_STATUS_USER_INTERVENTION)
601                 status_str = g_strdup (_("Need user intervention"));
602             }
603         }
604       else if (win32_status &
605                (JOB_STATUS_BLOCKED_DEVQ |
606                 JOB_STATUS_DELETED |
607                 JOB_STATUS_ERROR))
608         status = GTK_PRINT_STATUS_FINISHED_ABORTED;
609       else if (win32_status &
610                (JOB_STATUS_SPOOLING |
611                 JOB_STATUS_DELETING))
612         status = GTK_PRINT_STATUS_PENDING;
613       else if (win32_status & JOB_STATUS_PRINTING)
614         status = GTK_PRINT_STATUS_PRINTING;
615       else
616         status = GTK_PRINT_STATUS_FINISHED;
617     }
618   else
619     status = GTK_PRINT_STATUS_FINISHED;
620
621   g_free (data);
622
623   _gtk_print_operation_set_status (op, status, status_str);
624  
625   g_free (status_str);
626 }
627
628 static void
629 op_win32_free (GtkPrintOperationWin32 *op_win32)
630 {
631   if (op_win32->printerHandle)
632     ClosePrinter (op_win32->printerHandle);
633   if (op_win32->timeout_id != 0)
634     g_source_remove (op_win32->timeout_id);
635   g_free (op_win32);
636 }
637
638 static HWND
639 get_parent_hwnd (GtkWidget *widget)
640 {
641   gtk_widget_realize (widget);
642   return gdk_win32_drawable_get_handle (widget->window);
643 }
644
645 static void
646 devnames_to_settings (GtkPrintSettings *settings,
647                       HANDLE hDevNames)
648 {
649   GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
650   gtk_print_settings_set_printer (settings, devnames->device);
651   gtk_print_win32_devnames_free (devnames);
652 }
653
654 static void
655 devmode_to_settings (GtkPrintSettings *settings,
656                      HANDLE hDevMode)
657 {
658   LPDEVMODEW devmode;
659
660   devmode = GlobalLock (hDevMode);
661   
662   gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
663                               devmode->dmDriverVersion);
664   if (devmode->dmDriverExtra != 0)
665     {
666       char *extra = g_base64_encode (((char *)devmode) + sizeof (DEVMODEW),
667                                      devmode->dmDriverExtra);
668       gtk_print_settings_set (settings,
669                               GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
670                               extra);
671       g_free (extra);
672     }
673   
674   if (devmode->dmFields & DM_ORIENTATION)
675     gtk_print_settings_set_orientation (settings,
676                                         orientation_from_win32 (devmode->dmOrientation));
677   
678   
679   if (devmode->dmFields & DM_PAPERSIZE &&
680       devmode->dmPaperSize != 0)
681     {
682       GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
683       if (paper_size)
684         {
685           gtk_print_settings_set_paper_size (settings, paper_size);
686           gtk_paper_size_free (paper_size);
687         }
688       gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
689     }
690   else if ((devmode->dmFields & DM_PAPERSIZE &&
691             devmode->dmPaperSize == 0) ||
692            ((devmode->dmFields & DM_PAPERWIDTH) &&
693             (devmode->dmFields & DM_PAPERLENGTH)))
694     {
695       GtkPaperSize *paper_size;
696       char *form_name = NULL;
697       if (devmode->dmFields & DM_FORMNAME)
698         form_name = g_utf16_to_utf8 (devmode->dmFormName, 
699                                      -1, NULL, NULL, NULL);
700       if (form_name == NULL || form_name[0] == 0)
701         form_name = g_strdup (_("Custom size"));
702
703       /* Lengths in DEVMODE are in tenths of a millimeter */
704       paper_size = gtk_paper_size_new_custom (form_name,
705                                               form_name,
706                                               devmode->dmPaperWidth / 10.0,
707                                               devmode->dmPaperLength / 10.0,
708                                               GTK_UNIT_MM);
709       gtk_print_settings_set_paper_size (settings, paper_size);
710       gtk_paper_size_free (paper_size);
711     }
712   
713   if (devmode->dmFields & DM_SCALE)
714     gtk_print_settings_set_scale (settings, devmode->dmScale);
715   
716   if (devmode->dmFields & DM_COPIES)
717     gtk_print_settings_set_n_copies (settings,
718                                      devmode->dmCopies);
719   
720   if (devmode->dmFields & DM_DEFAULTSOURCE)
721     {
722       char *source;
723       switch (devmode->dmDefaultSource)
724         {
725         default:
726         case DMBIN_AUTO:
727           source = "auto";
728           break;
729         case DMBIN_CASSETTE:
730           source = "cassette";
731           break;
732         case DMBIN_ENVELOPE:
733           source = "envelope";
734           break;
735         case DMBIN_ENVMANUAL:
736           source = "envelope-manual";
737           break;
738         case DMBIN_LOWER:
739           source = "lower";
740           break;
741         case DMBIN_MANUAL:
742           source = "manual";
743           break;
744         case DMBIN_MIDDLE:
745           source = "middle";
746           break;
747         case DMBIN_ONLYONE:
748           source = "only-one";
749           break;
750         case DMBIN_FORMSOURCE:
751           source = "form-source";
752           break;
753         case DMBIN_LARGECAPACITY:
754           source = "large-capacity";
755           break;
756         case DMBIN_LARGEFMT:
757           source = "large-format";
758           break;
759         case DMBIN_TRACTOR:
760           source = "tractor";
761           break;
762         case DMBIN_SMALLFMT:
763           source = "small-format";
764           break;
765         }
766       gtk_print_settings_set_default_source (settings, source);
767       gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
768     }
769   
770   if (devmode->dmFields & DM_PRINTQUALITY)
771     {
772       GtkPrintQuality quality;
773       switch (devmode->dmPrintQuality)
774         {
775         case DMRES_LOW:
776           quality = GTK_PRINT_QUALITY_LOW;
777           break;
778         case DMRES_MEDIUM:
779           quality = GTK_PRINT_QUALITY_NORMAL;
780           break;
781         default:
782         case DMRES_HIGH:
783           quality = GTK_PRINT_QUALITY_HIGH;
784           break;
785         case DMRES_DRAFT:
786           quality = GTK_PRINT_QUALITY_DRAFT;
787           break;
788         }
789       gtk_print_settings_set_quality (settings, quality);
790       gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
791     }
792   
793   if (devmode->dmFields & DM_COLOR)
794     gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
795   
796   if (devmode->dmFields & DM_DUPLEX)
797     {
798       GtkPrintDuplex duplex;
799       switch (devmode->dmDuplex)
800         {
801         default:
802         case DMDUP_SIMPLEX:
803           duplex = GTK_PRINT_DUPLEX_SIMPLEX;
804           break;
805         case DMDUP_HORIZONTAL:
806           duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
807           break;
808         case DMDUP_VERTICAL:
809           duplex = GTK_PRINT_DUPLEX_VERTICAL;
810           break;
811         }
812       
813       gtk_print_settings_set_duplex (settings, duplex);
814     }
815   
816   if (devmode->dmFields & DM_COLLATE)
817     gtk_print_settings_set_collate (settings,
818                                     devmode->dmCollate == DMCOLLATE_TRUE);
819   
820   if (devmode->dmFields & DM_MEDIATYPE)
821     {
822       char *media_type;
823       switch (devmode->dmMediaType)
824         {
825         default:
826         case DMMEDIA_STANDARD:
827           media_type = "stationery";
828           break;
829         case DMMEDIA_TRANSPARENCY:
830           media_type = "transparency";
831           break;
832         case DMMEDIA_GLOSSY:
833           media_type = "photographic-glossy";
834           break;
835         }
836       gtk_print_settings_set_media_type (settings, media_type);
837       gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
838     }
839   
840   if (devmode->dmFields & DM_DITHERTYPE)
841     {
842       char *dither;
843       switch (devmode->dmDitherType)
844         {
845         default:
846         case DMDITHER_FINE:
847           dither = "fine";
848           break;
849         case DMDITHER_NONE:
850           dither = "none";
851           break;
852         case DMDITHER_COARSE:
853           dither = "coarse";
854           break;
855         case DMDITHER_LINEART:
856           dither = "lineart";
857           break;
858         case DMDITHER_GRAYSCALE:
859           dither = "grayscale";
860           break;
861         case DMDITHER_ERRORDIFFUSION:
862           dither = "error-diffusion";
863           break;
864         }
865       gtk_print_settings_set_dither (settings, dither);
866       gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
867     }
868   
869   GlobalUnlock (hDevMode);
870 }
871
872 static void
873 dialog_to_print_settings (GtkPrintOperation *op,
874                           LPPRINTDLGEXW printdlgex)
875 {
876   guint i;
877   GtkPrintSettings *settings;
878
879   settings = gtk_print_settings_new ();
880
881   gtk_print_settings_set_print_pages (settings,
882                                       GTK_PRINT_PAGES_ALL);
883   if (printdlgex->Flags & PD_CURRENTPAGE)
884     gtk_print_settings_set_print_pages (settings,
885                                         GTK_PRINT_PAGES_CURRENT);
886   else if (printdlgex->Flags & PD_PAGENUMS)
887     gtk_print_settings_set_print_pages (settings,
888                                         GTK_PRINT_PAGES_RANGES);
889
890   if (printdlgex->nPageRanges > 0)
891     {
892       GtkPageRange *ranges;
893       ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
894
895       for (i = 0; i < printdlgex->nPageRanges; i++)
896         {
897           ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
898           ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
899         }
900
901       gtk_print_settings_set_page_ranges (settings, ranges,
902                                           printdlgex->nPageRanges);
903       g_free (ranges);
904     }
905   
906   if (printdlgex->hDevNames != NULL)
907     devnames_to_settings (settings, printdlgex->hDevNames);
908
909   if (printdlgex->hDevMode != NULL)
910     devmode_to_settings (settings, printdlgex->hDevMode);
911   
912   gtk_print_operation_set_print_settings (op, settings);
913 }
914
915 static HANDLE
916 devmode_from_settings (GtkPrintSettings *settings,
917                        GtkPageSetup *page_setup)
918 {
919   HANDLE hDevMode;
920   LPDEVMODEW devmode;
921   char *extras;
922   GtkPaperSize *paper_size;
923   const char *extras_base64;
924   int extras_len;
925   const char *val;
926
927   extras = NULL;
928   extras_len = 0;
929   extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
930   if (extras_base64)
931     extras = g_base64_decode (extras_base64, &extras_len);
932   
933   hDevMode = GlobalAlloc (GMEM_MOVEABLE, 
934                           sizeof (DEVMODEW) + extras_len);
935
936   devmode = GlobalLock (hDevMode);
937
938   memset (devmode, 0, sizeof (DEVMODEW));
939   
940   devmode->dmSpecVersion = DM_SPECVERSION;
941   devmode->dmSize = sizeof (DEVMODEW);
942   
943   devmode->dmDriverExtra = 0;
944   if (extras && extras_len > 0)
945     {
946       devmode->dmDriverExtra = extras_len;
947       memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
948     }
949   g_free (extras);
950   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
951     devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
952   
953   if (page_setup ||
954       gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
955     {
956       GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
957       if (page_setup)
958         orientation = gtk_page_setup_get_orientation (page_setup);
959       devmode->dmFields |= DM_ORIENTATION;
960       devmode->dmOrientation = orientation_to_win32 (orientation);
961     }
962
963   if (page_setup)
964     paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
965   else
966     {
967       int size;
968       if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
969           (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
970         {
971           devmode->dmFields |= DM_PAPERSIZE;
972           devmode->dmPaperSize = size;
973           paper_size = NULL;
974         }
975       else
976         paper_size = gtk_print_settings_get_paper_size (settings);
977     }
978   if (paper_size)
979     {
980       devmode->dmFields |= DM_PAPERSIZE;
981       devmode->dmPaperSize = paper_size_to_win32 (paper_size);
982       if (devmode->dmPaperSize == 0)
983         {
984           devmode->dmPaperSize = DMPAPER_USER;
985           devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
986
987           /* Lengths in DEVMODE are in tenths of a millimeter */
988           devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
989           devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
990         }
991       gtk_paper_size_free (paper_size);
992     }
993
994   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
995     {
996       devmode->dmFields |= DM_SCALE;
997       devmode->dmScale = gtk_print_settings_get_scale (settings);
998     }
999   
1000   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
1001     {
1002       devmode->dmFields |= DM_COPIES;
1003       devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
1004     }
1005
1006   if (gtk_print_settings_has_key (settings, "win32-default-source"))
1007     {
1008       devmode->dmFields |= DM_DEFAULTSOURCE;
1009       devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
1010     }
1011   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
1012     {
1013       devmode->dmFields |= DM_DEFAULTSOURCE;
1014       devmode->dmDefaultSource = DMBIN_AUTO;
1015
1016       val = gtk_print_settings_get_default_source (settings);
1017       if (strcmp (val, "auto") == 0)
1018         devmode->dmDefaultSource = DMBIN_AUTO;
1019       if (strcmp (val, "cassette") == 0)
1020         devmode->dmDefaultSource = DMBIN_CASSETTE;
1021       if (strcmp (val, "envelope") == 0)
1022         devmode->dmDefaultSource = DMBIN_ENVELOPE;
1023       if (strcmp (val, "envelope-manual") == 0)
1024         devmode->dmDefaultSource = DMBIN_ENVMANUAL;
1025       if (strcmp (val, "lower") == 0)
1026         devmode->dmDefaultSource = DMBIN_LOWER;
1027       if (strcmp (val, "manual") == 0)
1028         devmode->dmDefaultSource = DMBIN_MANUAL;
1029       if (strcmp (val, "middle") == 0)
1030         devmode->dmDefaultSource = DMBIN_MIDDLE;
1031       if (strcmp (val, "only-one") == 0)
1032         devmode->dmDefaultSource = DMBIN_ONLYONE;
1033       if (strcmp (val, "form-source") == 0)
1034         devmode->dmDefaultSource = DMBIN_FORMSOURCE;
1035       if (strcmp (val, "large-capacity") == 0)
1036         devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
1037       if (strcmp (val, "large-format") == 0)
1038         devmode->dmDefaultSource = DMBIN_LARGEFMT;
1039       if (strcmp (val, "tractor") == 0)
1040         devmode->dmDefaultSource = DMBIN_TRACTOR;
1041       if (strcmp (val, "small-format") == 0)
1042         devmode->dmDefaultSource = DMBIN_SMALLFMT;
1043     }
1044
1045   if (gtk_print_settings_has_key (settings, "win32-print-quality"))
1046     {
1047       devmode->dmFields |= DM_PRINTQUALITY;
1048       devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
1049     }
1050   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
1051     {
1052       devmode->dmFields |= DM_PRINTQUALITY;
1053       devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
1054     } 
1055   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
1056     {
1057       devmode->dmFields |= DM_PRINTQUALITY;
1058       switch (gtk_print_settings_get_quality (settings))
1059         {
1060         case GTK_PRINT_QUALITY_LOW:
1061           devmode->dmPrintQuality = DMRES_LOW;
1062           break;
1063         case GTK_PRINT_QUALITY_DRAFT:
1064           devmode->dmPrintQuality = DMRES_DRAFT;
1065           break;
1066         default:
1067         case GTK_PRINT_QUALITY_NORMAL:
1068           devmode->dmPrintQuality = DMRES_MEDIUM;
1069           break;
1070         case GTK_PRINT_QUALITY_HIGH:
1071           devmode->dmPrintQuality = DMRES_HIGH;
1072           break;
1073         }
1074     }
1075
1076   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
1077     {
1078       devmode->dmFields |= DM_COLOR;
1079       if (gtk_print_settings_get_use_color (settings))
1080         devmode->dmColor = DMCOLOR_COLOR;
1081       else
1082         devmode->dmColor = DMCOLOR_MONOCHROME;
1083     }
1084
1085   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
1086     {
1087       devmode->dmFields |= DM_DUPLEX;
1088       switch (gtk_print_settings_get_duplex (settings))
1089         {
1090         default:
1091         case GTK_PRINT_DUPLEX_SIMPLEX:
1092           devmode->dmDuplex = DMDUP_SIMPLEX;
1093           break;
1094         case GTK_PRINT_DUPLEX_HORIZONTAL:
1095           devmode->dmDuplex = DMDUP_HORIZONTAL;
1096           break;
1097         case GTK_PRINT_DUPLEX_VERTICAL:
1098           devmode->dmDuplex = DMDUP_VERTICAL;
1099           break;
1100         }
1101     }
1102
1103   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
1104     {
1105       devmode->dmFields |= DM_COLLATE;
1106       if (gtk_print_settings_get_collate (settings))
1107         devmode->dmCollate = DMCOLLATE_TRUE;
1108       else
1109         devmode->dmCollate = DMCOLLATE_FALSE;
1110     }
1111
1112   if (gtk_print_settings_has_key (settings, "win32-media-type"))
1113     {
1114       devmode->dmFields |= DM_MEDIATYPE;
1115       devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
1116     }
1117   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
1118     {
1119       devmode->dmFields |= DM_MEDIATYPE;
1120       devmode->dmMediaType = DMMEDIA_STANDARD;
1121       
1122       val = gtk_print_settings_get_media_type (settings);
1123       if (strcmp (val, "transparency") == 0)
1124         devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
1125       if (strcmp (val, "photographic-glossy") == 0)
1126         devmode->dmMediaType = DMMEDIA_GLOSSY;
1127     }
1128  
1129   if (gtk_print_settings_has_key (settings, "win32-dither-type"))
1130     {
1131       devmode->dmFields |= DM_DITHERTYPE;
1132       devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
1133     }
1134   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
1135     {
1136       devmode->dmFields |= DM_DITHERTYPE;
1137       devmode->dmDitherType = DMDITHER_FINE;
1138       
1139       val = gtk_print_settings_get_dither (settings);
1140       if (strcmp (val, "none") == 0)
1141         devmode->dmDitherType = DMDITHER_NONE;
1142       if (strcmp (val, "coarse") == 0)
1143         devmode->dmDitherType = DMDITHER_COARSE;
1144       if (strcmp (val, "fine") == 0)
1145         devmode->dmDitherType = DMDITHER_FINE;
1146       if (strcmp (val, "lineart") == 0)
1147         devmode->dmDitherType = DMDITHER_LINEART;
1148       if (strcmp (val, "grayscale") == 0)
1149         devmode->dmDitherType = DMDITHER_GRAYSCALE;
1150       if (strcmp (val, "error-diffusion") == 0)
1151         devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
1152     }
1153   
1154   GlobalUnlock (hDevMode);
1155
1156   return hDevMode;
1157 }
1158
1159 static void
1160 dialog_from_print_settings (GtkPrintOperation *op,
1161                             LPPRINTDLGEXW printdlgex)
1162 {
1163   GtkPrintSettings *settings = op->priv->print_settings;
1164   const char *printer;
1165
1166   if (settings == NULL)
1167     return;
1168
1169   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
1170     {
1171       GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
1172
1173       switch (print_pages)
1174         {
1175         default:
1176         case GTK_PRINT_PAGES_ALL:
1177           printdlgex->Flags |= PD_ALLPAGES;
1178           break;
1179         case GTK_PRINT_PAGES_CURRENT:
1180           printdlgex->Flags |= PD_CURRENTPAGE;
1181           break;
1182         case GTK_PRINT_PAGES_RANGES:
1183           printdlgex->Flags |= PD_PAGENUMS;
1184           break;
1185         }
1186     }
1187   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
1188     {
1189       GtkPageRange *ranges;
1190       int num_ranges, i;
1191
1192       ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
1193
1194       if (num_ranges > MAX_PAGE_RANGES)
1195         num_ranges = MAX_PAGE_RANGES;
1196
1197       printdlgex->nPageRanges = num_ranges;
1198       for (i = 0; i < num_ranges; i++)
1199         {
1200           printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
1201           printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
1202         }
1203     }
1204   
1205   printer = gtk_print_settings_get_printer (settings);
1206   if (printer)
1207     printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1208   
1209   printdlgex->hDevMode = devmode_from_settings (settings,
1210                                                 op->priv->default_page_setup);
1211 }
1212
1213 typedef struct {
1214   IPrintDialogCallback iPrintDialogCallback;
1215   gboolean set_hwnd;
1216   int ref_count;
1217 } PrintDialogCallback;
1218
1219
1220 static ULONG STDMETHODCALLTYPE
1221 iprintdialogcallback_addref (IPrintDialogCallback *This)
1222 {
1223   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1224   return ++callback->ref_count;
1225 }
1226
1227 static ULONG STDMETHODCALLTYPE
1228 iprintdialogcallback_release (IPrintDialogCallback *This)
1229 {
1230   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1231   int ref_count = --callback->ref_count;
1232
1233   if (ref_count == 0)
1234     g_free (This);
1235
1236   return ref_count;
1237 }
1238
1239 static HRESULT STDMETHODCALLTYPE
1240 iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
1241                                      REFIID       riid,
1242                                      LPVOID      *ppvObject)
1243 {
1244    if (IsEqualIID (riid, &IID_IUnknown) ||
1245        IsEqualIID (riid, &myIID_IPrintDialogCallback))
1246      {
1247        *ppvObject = This;
1248        IUnknown_AddRef ((IUnknown *)This);
1249        return NOERROR;
1250      }
1251    else
1252      {
1253        *ppvObject = NULL;
1254        return E_NOINTERFACE;
1255      }
1256 }
1257
1258 static HRESULT STDMETHODCALLTYPE
1259 iprintdialogcallback_initdone (IPrintDialogCallback *This)
1260 {
1261   return S_FALSE;
1262 }
1263
1264 static HRESULT STDMETHODCALLTYPE
1265 iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
1266 {
1267   return S_FALSE;
1268 }
1269
1270 static HRESULT STDMETHODCALLTYPE
1271 iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
1272                                     HWND hDlg,
1273                                     UINT uMsg,
1274                                     WPARAM wParam,
1275                                     LPARAM lParam,
1276                                     LRESULT *pResult)
1277 {
1278   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1279
1280   if (!callback->set_hwnd)
1281     {
1282       gdk_win32_set_modal_dialog_libgtk_only (hDlg);
1283       callback->set_hwnd = TRUE;
1284       while (gtk_events_pending ())
1285         gtk_main_iteration ();
1286     }
1287   else if (uMsg == got_gdk_events_message)
1288     {
1289       while (gtk_events_pending ())
1290         gtk_main_iteration ();
1291       *pResult = TRUE;
1292       return S_OK;
1293     }
1294   
1295   *pResult = 0;
1296   return S_FALSE;
1297 }
1298
1299 static IPrintDialogCallbackVtbl ipdc_vtbl = {
1300   iprintdialogcallback_queryinterface,
1301   iprintdialogcallback_addref,
1302   iprintdialogcallback_release,
1303   iprintdialogcallback_initdone,
1304   iprintdialogcallback_selectionchange,
1305   iprintdialogcallback_handlemessage
1306 };
1307
1308 static IPrintDialogCallback *
1309 print_callback_new  (void)
1310 {
1311   PrintDialogCallback *callback;
1312
1313   callback = g_new0 (PrintDialogCallback, 1);
1314   callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
1315   callback->ref_count = 1;
1316   callback->set_hwnd = FALSE;
1317
1318   return &callback->iPrintDialogCallback;
1319 }
1320
1321 static  void
1322 plug_grab_notify (GtkWidget        *widget,
1323                   gboolean          was_grabbed,
1324                   GtkPrintOperation *op)
1325 {
1326   EnableWindow (GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
1327                 was_grabbed);
1328 }
1329
1330
1331 static BOOL CALLBACK
1332 pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1333 {
1334   GtkPrintOperation *op;
1335   GtkPrintOperationWin32 *op_win32;
1336   
1337   if (message == WM_INITDIALOG)
1338     {
1339       PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
1340       GtkWidget *plug;
1341
1342       op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
1343       op_win32 = op->priv->platform_data;
1344
1345       SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
1346       
1347       plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
1348       gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
1349       op_win32->embed_widget = plug;
1350       gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
1351       gtk_widget_show (op->priv->custom_widget);
1352       gtk_widget_show (plug);
1353       gdk_window_focus (plug->window, GDK_CURRENT_TIME);
1354
1355       /* This dialog is modal, so we grab the embed widget */
1356       gtk_grab_add (plug);
1357
1358       /* When we lose the grab we need to disable the print dialog */
1359       g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
1360       return FALSE;
1361     }
1362   else if (message == WM_DESTROY)
1363     {
1364       op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1365       op_win32 = op->priv->platform_data;
1366       
1367       g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
1368       gtk_widget_destroy (op_win32->embed_widget);
1369       op_win32->embed_widget = NULL;
1370       op->priv->custom_widget = NULL;
1371     }
1372   else 
1373     {
1374       op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1375       op_win32 = op->priv->platform_data;
1376
1377       return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
1378                                                        wnd, message, wparam, lparam);
1379     }
1380   
1381   return FALSE;
1382 }
1383
1384 static HPROPSHEETPAGE
1385 create_application_page (GtkPrintOperation *op)
1386 {
1387   HPROPSHEETPAGE hpage;
1388   PROPSHEETPAGEW page;
1389   DLGTEMPLATE *template;
1390   HGLOBAL htemplate;
1391   LONG base_units;
1392   WORD baseunitX, baseunitY;
1393   WORD *array;
1394   GtkRequisition requisition;
1395   const char *tab_label;
1396
1397   /* Make the template the size of the custom widget size request */
1398   gtk_widget_size_request (op->priv->custom_widget, &requisition);
1399       
1400   base_units = GetDialogBaseUnits ();
1401   baseunitX = LOWORD (base_units);
1402   baseunitY = HIWORD (base_units);
1403   
1404   htemplate = GlobalAlloc (GMEM_MOVEABLE, 
1405                            sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
1406   template = GlobalLock (htemplate);
1407   template->style = WS_CHILDWINDOW | DS_CONTROL;
1408   template->dwExtendedStyle = WS_EX_CONTROLPARENT;
1409   template->cdit = 0;
1410   template->x = MulDiv (0, 4, baseunitX);
1411   template->y = MulDiv (0, 8, baseunitY);
1412   template->cx = MulDiv (requisition.width, 4, baseunitX);
1413   template->cy = MulDiv (requisition.height, 8, baseunitY);
1414   
1415   array = (WORD *) (template+1);
1416   *array++ = 0; /* menu */
1417   *array++ = 0; /* class */
1418   *array++ = 0; /* title */
1419   
1420   memset (&page, 0, sizeof (page));
1421   page.dwSize = sizeof (page);
1422   page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
1423   page.hInstance = GetModuleHandle (NULL);
1424   page.pResource = template;
1425   
1426   tab_label = op->priv->custom_tab_label;
1427   if (tab_label == NULL)
1428     tab_label = g_get_application_name ();
1429   if (tab_label == NULL)
1430     tab_label = _("Application");
1431   page.pszTitle = g_utf8_to_utf16 (tab_label, 
1432                                    -1, NULL, NULL, NULL);
1433   page.pfnDlgProc = pageDlgProc;
1434   page.pfnCallback = NULL;
1435   page.lParam = (LPARAM) op;
1436   hpage = CreatePropertySheetPageW (&page);
1437   
1438   GlobalUnlock (htemplate);
1439   
1440   /* TODO: We're leaking htemplate here... */
1441   
1442   return hpage;
1443 }
1444
1445 static GtkPageSetup *
1446 create_page_setup (GtkPrintOperation *op)
1447 {
1448   GtkPrintOperationPrivate *priv = op->priv;
1449   GtkPageSetup *page_setup;
1450   GtkPrintSettings *settings;
1451   
1452   if (priv->default_page_setup)
1453     page_setup = gtk_page_setup_copy (priv->default_page_setup);
1454   else
1455     page_setup = gtk_page_setup_new ();
1456
1457   settings = priv->print_settings;
1458   if (settings)
1459     {
1460       GtkPaperSize *paper_size;
1461       
1462       if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1463         gtk_page_setup_set_orientation (page_setup,
1464                                         gtk_print_settings_get_orientation (settings));
1465
1466
1467       paper_size = gtk_print_settings_get_paper_size (settings);
1468       if (paper_size)
1469         {
1470           gtk_page_setup_set_paper_size (page_setup, paper_size);
1471           gtk_paper_size_free (paper_size);
1472         }
1473
1474       /* TODO: Margins? */
1475     }
1476   
1477   return page_setup;
1478 }
1479
1480 GtkPrintOperationResult
1481 gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
1482                                         gboolean          *do_print)
1483 {
1484   GtkPrintOperationResult result;
1485   GtkPrintOperationWin32 *op_win32;
1486   GtkPrintOperationPrivate *priv;
1487   GtkPrintSettings *settings;
1488   GtkPageSetup *page_setup;
1489   DOCINFOW docinfo;
1490   HGLOBAL hDevMode = NULL;
1491   HGLOBAL hDevNames = NULL;
1492   HDC hDC = NULL;
1493   const char *printer = NULL;
1494   double dpi_x, dpi_y;
1495   int job_id;
1496   cairo_t *cr;
1497   DEVNAMES *pdn;
1498   DEVMODEW *pdm;
1499
1500   *do_print = FALSE;
1501
1502   priv = op->priv;
1503   settings = priv->print_settings;
1504   
1505   op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1506   priv->platform_data = op_win32;
1507   priv->free_platform_data = (GDestroyNotify) op_win32_free;
1508   printer = gtk_print_settings_get_printer (settings);
1509
1510   if (!printer)
1511     {
1512       /* No printer selected. Get the system default printer and store
1513        * it in settings.
1514        */
1515       gchar *tmp_printer = get_default_printer ();
1516       if (!tmp_printer)
1517         {
1518           result = GTK_PRINT_OPERATION_RESULT_ERROR;
1519           g_set_error_literal (&priv->error,
1520                                GTK_PRINT_ERROR,
1521                                GTK_PRINT_ERROR_INTERNAL_ERROR,
1522                                _("No printer found"));
1523           goto out;
1524         }
1525       gtk_print_settings_set_printer (settings, tmp_printer);
1526       printer = gtk_print_settings_get_printer (settings);
1527       g_free (tmp_printer);
1528     }
1529
1530   hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1531   hDevMode = devmode_from_settings (settings, op->priv->default_page_setup);
1532
1533   /* Create a printer DC for the print settings and page setup provided. */
1534   pdn = GlobalLock (hDevNames);
1535   pdm = GlobalLock (hDevMode);
1536   hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
1537                    (wchar_t*)pdn + pdn->wDeviceOffset,
1538                    (wchar_t*)pdn + pdn->wOutputOffset,
1539                    pdm );
1540   GlobalUnlock (hDevNames);
1541   GlobalUnlock (hDevMode);
1542
1543   if (!hDC)
1544     {
1545       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1546       g_set_error_literal (&priv->error,
1547                            GTK_PRINT_ERROR,
1548                            GTK_PRINT_ERROR_INTERNAL_ERROR,
1549                            _("Invalid argument to CreateDC"));
1550       goto out;
1551     }
1552   
1553   priv->print_context = _gtk_print_context_new (op);
1554   page_setup = create_page_setup (op);
1555   _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1556   g_object_unref (page_setup);
1557
1558   *do_print = TRUE;
1559
1560   op_win32->surface = cairo_win32_printing_surface_create (hDC);
1561   dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
1562   dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
1563
1564   cr = cairo_create (op_win32->surface);
1565   gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1566   cairo_destroy (cr);
1567
1568   memset (&docinfo, 0, sizeof (DOCINFOW));
1569   docinfo.cbSize = sizeof (DOCINFOW); 
1570   docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
1571   docinfo.lpszOutput = NULL; 
1572   docinfo.lpszDatatype = NULL; 
1573   docinfo.fwType = 0; 
1574
1575   job_id = StartDocW (hDC, &docinfo); 
1576   g_free ((void *)docinfo.lpszDocName);
1577   if (job_id <= 0)
1578     { 
1579       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1580       g_set_error_literal (&priv->error,
1581                            GTK_PRINT_ERROR,
1582                            GTK_PRINT_ERROR_GENERAL,
1583                            _("Error from StartDoc"));
1584       *do_print = FALSE;
1585       cairo_surface_destroy (op_win32->surface);
1586       op_win32->surface = NULL;
1587       goto out; 
1588     }
1589
1590   result = GTK_PRINT_OPERATION_RESULT_APPLY;
1591   op_win32->hdc = hDC;
1592   op_win32->devmode = hDevMode;
1593   op_win32->devnames = hDevNames;
1594   op_win32->job_id = job_id;
1595   op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1596   op->priv->num_page_ranges = 0;
1597   if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1598     op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1599                                                                 &op->priv->num_page_ranges);
1600   op->priv->manual_num_copies = 1;
1601   op->priv->manual_collation = FALSE;
1602   op->priv->manual_reverse = FALSE;
1603   op->priv->manual_orientation = FALSE;
1604   op->priv->manual_scale = 1.0;
1605   op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1606   op->priv->manual_number_up = 1;
1607   op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1608
1609   op->priv->start_page = win32_start_page;
1610   op->priv->end_page = win32_end_page;
1611   op->priv->end_run = win32_end_run;
1612   
1613  out:
1614   if (!*do_print && hDC != NULL)
1615     DeleteDC (hDC);
1616
1617   if (!*do_print && hDevMode != NULL)
1618     GlobalFree (hDevMode);
1619
1620   if (!*do_print && hDevNames != NULL)
1621     GlobalFree (hDevNames);
1622
1623   return result;
1624 }
1625
1626 GtkPrintOperationResult
1627 gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
1628                                      GtkWindow         *parent,
1629                                      gboolean          *do_print)
1630 {
1631   HRESULT hResult;
1632   LPPRINTDLGEXW printdlgex = NULL;
1633   LPPRINTPAGERANGE page_ranges = NULL;
1634   HWND parentHWnd;
1635   GtkWidget *invisible = NULL;
1636   GtkPrintOperationResult result;
1637   GtkPrintOperationWin32 *op_win32;
1638   GtkPrintOperationPrivate *priv;
1639   IPrintDialogCallback *callback;
1640   HPROPSHEETPAGE prop_page;
1641   
1642   *do_print = FALSE;
1643
1644   priv = op->priv;
1645   
1646   op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1647   priv->platform_data = op_win32;
1648   priv->free_platform_data = (GDestroyNotify) op_win32_free;
1649   
1650   if (parent == NULL)
1651     {
1652       invisible = gtk_invisible_new ();
1653       parentHWnd = get_parent_hwnd (invisible);
1654     }
1655   else 
1656     parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
1657
1658   printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
1659   if (!printdlgex)
1660     {
1661       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1662       g_set_error_literal (&priv->error,
1663                            GTK_PRINT_ERROR,
1664                            GTK_PRINT_ERROR_NOMEM,
1665                            _("Not enough free memory"));
1666       goto out;
1667     }      
1668
1669   printdlgex->lStructSize = sizeof (PRINTDLGEXW);
1670   printdlgex->hwndOwner = parentHWnd;
1671   printdlgex->hDevMode = NULL;
1672   printdlgex->hDevNames = NULL;
1673   printdlgex->hDC = NULL;
1674   printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
1675   if (op->priv->current_page == -1)
1676     printdlgex->Flags |= PD_NOCURRENTPAGE;
1677   printdlgex->Flags2 = 0;
1678   printdlgex->ExclusionFlags = 0;
1679
1680   page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR, 
1681                                                 MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
1682   if (!page_ranges) 
1683     {
1684       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1685       g_set_error_literal (&priv->error,
1686                            GTK_PRINT_ERROR,
1687                            GTK_PRINT_ERROR_NOMEM,
1688                            _("Not enough free memory"));
1689       goto out;
1690     }
1691
1692   printdlgex->nPageRanges = 0;
1693   printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
1694   printdlgex->lpPageRanges = page_ranges;
1695   printdlgex->nMinPage = 1;
1696   if (op->priv->nr_of_pages != -1)
1697     printdlgex->nMaxPage = op->priv->nr_of_pages;
1698   else
1699     printdlgex->nMaxPage = 10000;
1700   printdlgex->nCopies = 1;
1701   printdlgex->hInstance = 0;
1702   printdlgex->lpPrintTemplateName = NULL;
1703   printdlgex->lpCallback = NULL;
1704
1705   g_signal_emit_by_name (op, "create-custom-widget",
1706                          &op->priv->custom_widget);
1707   if (op->priv->custom_widget) {
1708     prop_page = create_application_page (op);
1709     printdlgex->nPropertyPages = 1;
1710     printdlgex->lphPropertyPages = &prop_page;
1711   } else {
1712     printdlgex->nPropertyPages = 0;
1713     printdlgex->lphPropertyPages = NULL;
1714   }
1715   
1716   printdlgex->nStartPage = START_PAGE_GENERAL;
1717   printdlgex->dwResultAction = 0;
1718
1719   dialog_from_print_settings (op, printdlgex);
1720
1721   callback = print_callback_new ();
1722   printdlgex->lpCallback = (IUnknown *)callback;
1723   got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1724
1725   hResult = PrintDlgExW (printdlgex);
1726   IUnknown_Release ((IUnknown *)callback);
1727   gdk_win32_set_modal_dialog_libgtk_only (NULL);
1728
1729   if (hResult != S_OK) 
1730     {
1731       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1732       if (hResult == E_OUTOFMEMORY)
1733         g_set_error_literal (&priv->error,
1734                              GTK_PRINT_ERROR,
1735                              GTK_PRINT_ERROR_NOMEM,
1736                              _("Not enough free memory"));
1737       else if (hResult == E_INVALIDARG)
1738         g_set_error_literal (&priv->error,
1739                              GTK_PRINT_ERROR,
1740                              GTK_PRINT_ERROR_INTERNAL_ERROR,
1741                              _("Invalid argument to PrintDlgEx"));
1742       else if (hResult == E_POINTER)
1743         g_set_error_literal (&priv->error,
1744                              GTK_PRINT_ERROR,
1745                              GTK_PRINT_ERROR_INTERNAL_ERROR,
1746                              _("Invalid pointer to PrintDlgEx"));
1747       else if (hResult == E_HANDLE)
1748         g_set_error_literal (&priv->error,
1749                              GTK_PRINT_ERROR,
1750                              GTK_PRINT_ERROR_INTERNAL_ERROR,
1751                              _("Invalid handle to PrintDlgEx"));
1752       else /* E_FAIL */
1753         g_set_error_literal (&priv->error,
1754                              GTK_PRINT_ERROR,
1755                              GTK_PRINT_ERROR_GENERAL,
1756                              _("Unspecified error"));
1757       goto out;
1758     }
1759
1760   if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
1761       printdlgex->dwResultAction == PD_RESULT_APPLY)
1762     {
1763       result = GTK_PRINT_OPERATION_RESULT_APPLY;
1764       dialog_to_print_settings (op, printdlgex);
1765     }
1766   else
1767     result = GTK_PRINT_OPERATION_RESULT_CANCEL;
1768   
1769   if (printdlgex->dwResultAction == PD_RESULT_PRINT)
1770     {
1771       DOCINFOW docinfo;
1772       int job_id;
1773       double dpi_x, dpi_y;
1774       cairo_t *cr;
1775       GtkPageSetup *page_setup;
1776
1777       priv->print_context = _gtk_print_context_new (op);
1778       page_setup = create_page_setup (op);
1779       _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1780       g_object_unref (page_setup);
1781       
1782       *do_print = TRUE;
1783
1784       op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
1785
1786       dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
1787       dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
1788
1789       cr = cairo_create (op_win32->surface);
1790       gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1791       cairo_destroy (cr);
1792       
1793       memset ( &docinfo, 0, sizeof (DOCINFOW));
1794       docinfo.cbSize = sizeof (DOCINFOW); 
1795       docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
1796       docinfo.lpszOutput = (LPCWSTR) NULL; 
1797       docinfo.lpszDatatype = (LPCWSTR) NULL; 
1798       docinfo.fwType = 0; 
1799
1800       job_id = StartDocW (printdlgex->hDC, &docinfo); 
1801       g_free ((void *)docinfo.lpszDocName);
1802       if (job_id <= 0) 
1803         {
1804           result = GTK_PRINT_OPERATION_RESULT_ERROR;
1805           g_set_error_literal (&priv->error,
1806                                GTK_PRINT_ERROR,
1807                                GTK_PRINT_ERROR_GENERAL,
1808                                _("Error from StartDoc"));
1809           *do_print = FALSE;
1810           cairo_surface_destroy (op_win32->surface);
1811           op_win32->surface = NULL;
1812           goto out; 
1813         } 
1814       
1815       op_win32->hdc = printdlgex->hDC;
1816       op_win32->devmode = printdlgex->hDevMode;
1817       op_win32->devnames = printdlgex->hDevNames;
1818       op_win32->job_id = job_id;
1819       
1820       op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1821       op->priv->num_page_ranges = 0;
1822       if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1823         op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1824                                                                     &op->priv->num_page_ranges);
1825       op->priv->manual_num_copies = printdlgex->nCopies;
1826       op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
1827       op->priv->manual_reverse = FALSE;
1828       op->priv->manual_orientation = FALSE;
1829       op->priv->manual_scale = 1.0;
1830       op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1831       op->priv->manual_number_up = 1;
1832       op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1833     }
1834
1835   op->priv->start_page = win32_start_page;
1836   op->priv->end_page = win32_end_page;
1837   op->priv->end_run = win32_end_run;
1838   
1839   out:
1840   if (!*do_print && printdlgex && printdlgex->hDC != NULL)
1841     DeleteDC (printdlgex->hDC);
1842
1843   if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) 
1844     GlobalFree (printdlgex->hDevMode); 
1845
1846   if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) 
1847     GlobalFree (printdlgex->hDevNames); 
1848
1849   if (page_ranges)
1850     GlobalFree (page_ranges);
1851
1852   if (printdlgex)
1853     GlobalFree (printdlgex);
1854
1855   if (invisible)
1856     gtk_widget_destroy (invisible);
1857
1858   return result;
1859 }
1860
1861 GtkPrintOperationResult
1862 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
1863                                                   gboolean           show_dialog,
1864                                                   GtkWindow         *parent,
1865                                                   gboolean          *do_print)
1866 {
1867   if (show_dialog)
1868     return gtk_print_operation_run_with_dialog (op, parent, do_print);
1869   else
1870     return gtk_print_operation_run_without_dialog (op, do_print);
1871 }
1872
1873 void
1874 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
1875                                                       cairo_surface_t   *surface,
1876                                                       GtkWindow         *parent,
1877                                                       const gchar       *filename)
1878 {
1879   HDC dc;
1880   HENHMETAFILE metafile;
1881   
1882   dc = cairo_win32_surface_get_dc (surface);
1883   cairo_surface_destroy (surface);
1884   metafile = CloseEnhMetaFile (dc);
1885   DeleteEnhMetaFile (metafile);
1886   
1887   ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
1888 }
1889
1890 void
1891 _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
1892                                                           cairo_surface_t *surface,
1893                                                           cairo_t *cr)
1894 {
1895   HDC dc = cairo_win32_surface_get_dc (surface);
1896   StartPage (dc);
1897 }
1898
1899 void
1900 _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
1901                                                         cairo_surface_t *surface,
1902                                                         cairo_t *cr)
1903 {
1904   HDC dc;
1905
1906   cairo_surface_show_page (surface);
1907
1908   /* TODO: Enhanced metafiles don't support multiple pages.
1909    */
1910   dc = cairo_win32_surface_get_dc (surface);
1911   EndPage (dc);
1912 }
1913
1914 cairo_surface_t *
1915 _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
1916                                                               GtkPageSetup      *page_setup,
1917                                                               gdouble           *dpi_x,
1918                                                               gdouble           *dpi_y,
1919                                                               gchar            **target)
1920 {
1921   GtkPaperSize *paper_size;
1922   HDC metafile_dc;
1923   RECT rect;
1924   char *template;
1925   char *filename;
1926   gunichar2 *filename_utf16;
1927   int fd;
1928
1929   template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
1930   fd = g_mkstemp (template);
1931   close (fd);
1932
1933   filename = g_strconcat (template, ".emf", NULL);
1934   g_free (template);
1935   
1936   filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1937   g_free (filename);
1938
1939   paper_size = gtk_page_setup_get_paper_size (page_setup);
1940
1941   /* The rectangle dimensions are given in hundredths of a millimeter */
1942   rect.left = 0;
1943   rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
1944   rect.top = 0;
1945   rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
1946   
1947   metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
1948                                     &rect, L"Gtk+\0Print Preview\0\0");
1949   if (metafile_dc == NULL)
1950     {
1951       g_warning ("Can't create metafile");
1952       return NULL;
1953     }
1954
1955   *target = (char *)filename_utf16;
1956   
1957   *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
1958   *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
1959
1960   return cairo_win32_printing_surface_create (metafile_dc);
1961 }
1962
1963 void
1964 _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
1965                                                               GtkPageSetup      *page_setup,
1966                                                               cairo_surface_t   *surface)
1967 {
1968   /* TODO: Implement */
1969 }
1970
1971 GtkPageSetup *
1972 gtk_print_run_page_setup_dialog (GtkWindow        *parent,
1973                                  GtkPageSetup     *page_setup,
1974                                  GtkPrintSettings *settings)
1975 {
1976   LPPAGESETUPDLGW pagesetupdlg = NULL;
1977   BOOL res;
1978   gboolean free_settings;
1979   const char *printer;
1980   GtkPaperSize *paper_size;
1981   DWORD measure_system;
1982   GtkUnit unit;
1983   double scale;
1984
1985   pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
1986   if (!pagesetupdlg)
1987     return NULL;
1988
1989   free_settings = FALSE;
1990   if (settings == NULL)
1991     {
1992       settings = gtk_print_settings_new ();
1993       free_settings = TRUE;
1994     }
1995   
1996   memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
1997
1998   pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
1999
2000   if (parent != NULL)
2001     pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
2002   else
2003     pagesetupdlg->hwndOwner = NULL;
2004
2005   pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
2006   pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup);
2007   pagesetupdlg->hDevNames = NULL;
2008   printer = gtk_print_settings_get_printer (settings);
2009   if (printer)
2010     pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
2011
2012   GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
2013                   (LPWSTR)&measure_system, sizeof (DWORD));
2014
2015   if (measure_system == 0)
2016     {
2017       pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2018       unit = GTK_UNIT_MM;
2019       scale = 100;
2020     }
2021   else
2022     {
2023       pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
2024       unit = GTK_UNIT_INCH;
2025       scale = 1000;
2026     }
2027
2028   /* This is the object we return, we allocate it here so that
2029    * we can use the default page margins */
2030   if (page_setup)
2031     page_setup = gtk_page_setup_copy (page_setup);
2032   else
2033     page_setup = gtk_page_setup_new ();
2034   
2035   pagesetupdlg->Flags |= PSD_MARGINS;
2036   pagesetupdlg->rtMargin.left =
2037     floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
2038   pagesetupdlg->rtMargin.right =
2039     floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
2040   pagesetupdlg->rtMargin.top = 
2041     floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
2042   pagesetupdlg->rtMargin.bottom =
2043     floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
2044
2045   pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
2046   pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
2047   got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
2048   
2049   res = PageSetupDlgW (pagesetupdlg);
2050   gdk_win32_set_modal_dialog_libgtk_only (NULL);
2051
2052   if (res)
2053     {  
2054       if (pagesetupdlg->hDevNames != NULL)
2055         devnames_to_settings (settings, pagesetupdlg->hDevNames);
2056
2057       if (pagesetupdlg->hDevMode != NULL)
2058         devmode_to_settings (settings, pagesetupdlg->hDevMode);
2059     }
2060   
2061   if (res)
2062     {
2063       gtk_page_setup_set_orientation (page_setup, 
2064                                       gtk_print_settings_get_orientation (settings));
2065       paper_size = gtk_print_settings_get_paper_size (settings);
2066       if (paper_size)
2067         {
2068           gtk_page_setup_set_paper_size (page_setup, paper_size);
2069           gtk_paper_size_free (paper_size);
2070         }
2071
2072       if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2073         {
2074           unit = GTK_UNIT_MM;
2075           scale = 100;
2076         }
2077       else
2078         {
2079           unit = GTK_UNIT_INCH;
2080           scale = 1000;
2081         }
2082
2083       gtk_page_setup_set_left_margin (page_setup,
2084                                       pagesetupdlg->rtMargin.left / scale,
2085                                       unit);
2086       gtk_page_setup_set_right_margin (page_setup,
2087                                        pagesetupdlg->rtMargin.right / scale,
2088                                        unit);
2089       gtk_page_setup_set_top_margin (page_setup,
2090                                      pagesetupdlg->rtMargin.top / scale,
2091                                      unit);
2092       gtk_page_setup_set_bottom_margin (page_setup,
2093                                         pagesetupdlg->rtMargin.bottom / scale,
2094                                         unit);
2095     }
2096   
2097   if (free_settings)
2098     g_object_unref (settings);
2099
2100   return page_setup;
2101 }
2102
2103 void
2104 gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
2105                                        GtkPageSetup         *page_setup,
2106                                        GtkPrintSettings     *settings,
2107                                        GtkPageSetupDoneFunc  done_cb,
2108                                        gpointer              data)
2109 {
2110   GtkPageSetup *new_page_setup;
2111
2112   new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
2113   done_cb (new_page_setup, data);
2114   g_object_unref (new_page_setup);
2115 }
2116
2117 #define __GTK_PRINT_OPERATION_WIN32_C__
2118 #include "gtkaliasdef.c"