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