]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintoperation-win32.c
Set the GtkWin32EmbedWidget we create here as modal. Fixes #389358.
[~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 #ifndef _MSC_VER
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 void
420 win32_start_page (GtkPrintOperation *op,
421                   GtkPrintContext *print_context,
422                   GtkPageSetup *page_setup)
423 {
424   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
425   LPDEVMODEW devmode;
426   GtkPaperSize *paper_size;
427
428   devmode = GlobalLock (op_win32->devmode);
429   
430   devmode->dmFields |= DM_ORIENTATION;
431   devmode->dmOrientation =
432     orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
433   
434   paper_size = gtk_page_setup_get_paper_size (page_setup);
435   devmode->dmFields |= DM_PAPERSIZE;
436   devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
437   devmode->dmPaperSize = paper_size_to_win32 (paper_size);
438   if (devmode->dmPaperSize == 0)
439     {
440       devmode->dmPaperSize = DMPAPER_USER;
441       devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
442       devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
443       devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
444     }
445   
446   ResetDCW (op_win32->hdc, devmode);
447   
448   GlobalUnlock (op_win32->devmode);
449   
450   StartPage (op_win32->hdc);
451 }
452
453 static void
454 win32_end_page (GtkPrintOperation *op,
455                 GtkPrintContext *print_context)
456 {
457   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
458   EndPage (op_win32->hdc);
459 }
460
461 static gboolean
462 win32_poll_status_timeout (GtkPrintOperation *op)
463 {
464   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
465   
466   op_win32->timeout_id = 0;
467   /* We need to ref this, as setting the status to finished
468      might unref the object */
469   g_object_ref (op);
470   win32_poll_status (op);
471
472   if (!gtk_print_operation_is_finished (op))
473     op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
474                                           (GSourceFunc)win32_poll_status_timeout,
475                                           op);
476   g_object_unref (op);
477   return FALSE;
478 }
479
480
481 static void
482 win32_end_run (GtkPrintOperation *op,
483                gboolean           wait,
484                gboolean           cancelled)
485 {
486   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
487   LPDEVNAMES devnames;
488   HANDLE printerHandle = 0;
489   
490   EndDoc (op_win32->hdc);
491
492   if (op->priv->track_print_status)
493     {
494       devnames = GlobalLock (op_win32->devnames);
495       if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
496                          &printerHandle, NULL))
497         printerHandle = 0;
498       GlobalUnlock (op_win32->devnames);
499     }
500   
501   GlobalFree(op_win32->devmode);
502   GlobalFree(op_win32->devnames);
503
504   cairo_surface_finish (op_win32->surface);
505   cairo_surface_destroy (op_win32->surface);
506   op_win32->surface = NULL;
507
508   DeleteDC(op_win32->hdc);
509   
510   if (printerHandle != 0)
511     {
512       op_win32->printerHandle = printerHandle;
513       win32_poll_status (op);
514       op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
515                                             (GSourceFunc)win32_poll_status_timeout,
516                                             op);
517     }
518   else
519     /* Dunno what happened, pretend its finished */
520     _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
521 }
522
523 static void
524 win32_poll_status (GtkPrintOperation *op)
525 {
526   GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
527   guchar *data;
528   DWORD needed;
529   JOB_INFO_1W *job_info;
530   GtkPrintStatus status;
531   char *status_str;
532   BOOL ret;
533
534   GetJobW (op_win32->printerHandle, op_win32->job_id,
535            1,(LPBYTE)NULL, 0, &needed);
536   data = g_malloc (needed);
537   ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
538                  1, (LPBYTE)data, needed, &needed);
539
540   status_str = NULL;
541   if (ret)
542     {
543       DWORD win32_status;
544       job_info = (JOB_INFO_1W *)data;
545       win32_status = job_info->Status;
546
547       if (job_info->pStatus)
548         status_str = g_utf16_to_utf8 (job_info->pStatus, 
549                                       -1, NULL, NULL, NULL);
550      
551       if (win32_status &
552           (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
553         status = GTK_PRINT_STATUS_FINISHED;
554       else if (win32_status &
555                (JOB_STATUS_OFFLINE |
556                 JOB_STATUS_PAPEROUT |
557                 JOB_STATUS_PAUSED |
558                 JOB_STATUS_USER_INTERVENTION))
559         {
560           status = GTK_PRINT_STATUS_PENDING_ISSUE;
561           if (status_str == NULL)
562             {
563               if (win32_status & JOB_STATUS_OFFLINE)
564                 status_str = g_strdup (_("Printer offline"));
565               else if (win32_status & JOB_STATUS_PAPEROUT)
566                 status_str = g_strdup (_("Out of paper"));
567               else if (win32_status & JOB_STATUS_PAUSED)
568                 status_str = g_strdup (_("Paused"));
569               else if (win32_status & JOB_STATUS_USER_INTERVENTION)
570                 status_str = g_strdup (_("Need user intervention"));
571             }
572         }
573       else if (win32_status &
574                (JOB_STATUS_BLOCKED_DEVQ |
575                 JOB_STATUS_DELETED |
576                 JOB_STATUS_ERROR))
577         status = GTK_PRINT_STATUS_FINISHED_ABORTED;
578       else if (win32_status &
579                (JOB_STATUS_SPOOLING |
580                 JOB_STATUS_DELETING))
581         status = GTK_PRINT_STATUS_PENDING;
582       else if (win32_status & JOB_STATUS_PRINTING)
583         status = GTK_PRINT_STATUS_PRINTING;
584       else
585         status = GTK_PRINT_STATUS_FINISHED;
586     }
587   else
588     status = GTK_PRINT_STATUS_FINISHED;
589
590   g_free (data);
591
592   _gtk_print_operation_set_status (op, status, status_str);
593  
594   g_free (status_str);
595 }
596
597 static void
598 op_win32_free (GtkPrintOperationWin32 *op_win32)
599 {
600   if (op_win32->printerHandle)
601     ClosePrinter (op_win32->printerHandle);
602   if (op_win32->timeout_id != 0)
603     g_source_remove (op_win32->timeout_id);
604   g_free (op_win32);
605 }
606
607 static HWND
608 get_parent_hwnd (GtkWidget *widget)
609 {
610   gtk_widget_realize (widget);
611   return gdk_win32_drawable_get_handle (widget->window);
612 }
613
614 static void
615 devnames_to_settings (GtkPrintSettings *settings,
616                       HANDLE hDevNames)
617 {
618   GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
619   gtk_print_settings_set_printer (settings, devnames->device);
620   gtk_print_win32_devnames_free (devnames);
621 }
622
623 static void
624 devmode_to_settings (GtkPrintSettings *settings,
625                      HANDLE hDevMode)
626 {
627   LPDEVMODEW devmode;
628
629   devmode = GlobalLock (hDevMode);
630   
631   gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
632                               devmode->dmDriverVersion);
633   if (devmode->dmDriverExtra != 0)
634     {
635       char *extra = g_base64_encode (((char *)devmode) + sizeof (DEVMODEW),
636                                      devmode->dmDriverExtra);
637       gtk_print_settings_set (settings,
638                               GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
639                               extra);
640       g_free (extra);
641     }
642   
643   if (devmode->dmFields & DM_ORIENTATION)
644     gtk_print_settings_set_orientation (settings,
645                                         orientation_from_win32 (devmode->dmOrientation));
646   
647   
648   if (devmode->dmFields & DM_PAPERSIZE &&
649       devmode->dmPaperSize != 0)
650     {
651       GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
652       if (paper_size)
653         {
654           gtk_print_settings_set_paper_size (settings, paper_size);
655           gtk_paper_size_free (paper_size);
656         }
657       gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
658     }
659   else if ((devmode->dmFields & DM_PAPERSIZE &&
660             devmode->dmPaperSize == 0) ||
661            ((devmode->dmFields & DM_PAPERWIDTH) &&
662             (devmode->dmFields & DM_PAPERLENGTH)))
663     {
664       GtkPaperSize *paper_size;
665       char *form_name = NULL;
666       if (devmode->dmFields & DM_FORMNAME)
667         form_name = g_utf16_to_utf8 (devmode->dmFormName, 
668                                      -1, NULL, NULL, NULL);
669       if (form_name == NULL || form_name[0] == 0)
670         form_name = g_strdup (_("Custom size"));
671       paper_size = gtk_paper_size_new_custom (form_name,
672                                               form_name,
673                                               devmode->dmPaperWidth * 10.0,
674                                               devmode->dmPaperLength * 10.0,
675                                               GTK_UNIT_MM);
676       gtk_print_settings_set_paper_size (settings, paper_size);
677       gtk_paper_size_free (paper_size);
678     }
679   
680   if (devmode->dmFields & DM_SCALE)
681     gtk_print_settings_set_scale (settings, devmode->dmScale);
682   
683   if (devmode->dmFields & DM_COPIES)
684     gtk_print_settings_set_n_copies (settings,
685                                      devmode->dmCopies);
686   
687   if (devmode->dmFields & DM_DEFAULTSOURCE)
688     {
689       char *source;
690       switch (devmode->dmDefaultSource)
691         {
692         default:
693         case DMBIN_AUTO:
694           source = "auto";
695           break;
696         case DMBIN_CASSETTE:
697           source = "cassette";
698           break;
699         case DMBIN_ENVELOPE:
700           source = "envelope";
701           break;
702         case DMBIN_ENVMANUAL:
703           source = "envelope-manual";
704           break;
705         case DMBIN_LOWER:
706           source = "lower";
707           break;
708         case DMBIN_MANUAL:
709           source = "manual";
710           break;
711         case DMBIN_MIDDLE:
712           source = "middle";
713           break;
714         case DMBIN_ONLYONE:
715           source = "only-one";
716           break;
717         case DMBIN_FORMSOURCE:
718           source = "form-source";
719           break;
720         case DMBIN_LARGECAPACITY:
721           source = "large-capacity";
722           break;
723         case DMBIN_LARGEFMT:
724           source = "large-format";
725           break;
726         case DMBIN_TRACTOR:
727           source = "tractor";
728           break;
729         case DMBIN_SMALLFMT:
730           source = "small-format";
731           break;
732         }
733       gtk_print_settings_set_default_source (settings, source);
734       gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
735     }
736   
737   if (devmode->dmFields & DM_PRINTQUALITY)
738     {
739       GtkPrintQuality quality;
740       switch (devmode->dmPrintQuality)
741         {
742         case DMRES_LOW:
743           quality = GTK_PRINT_QUALITY_LOW;
744           break;
745         case DMRES_MEDIUM:
746           quality = GTK_PRINT_QUALITY_NORMAL;
747           break;
748         default:
749         case DMRES_HIGH:
750           quality = GTK_PRINT_QUALITY_HIGH;
751           break;
752         case DMRES_DRAFT:
753           quality = GTK_PRINT_QUALITY_DRAFT;
754           break;
755         }
756       gtk_print_settings_set_quality (settings, quality);
757       gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
758     }
759   
760   if (devmode->dmFields & DM_COLOR)
761     gtk_print_settings_set_use_color (settings, devmode->dmFields == DMCOLOR_COLOR);
762   
763   if (devmode->dmFields & DM_DUPLEX)
764     {
765       GtkPrintDuplex duplex;
766       switch (devmode->dmDuplex)
767         {
768         default:
769         case DMDUP_SIMPLEX:
770           duplex = GTK_PRINT_DUPLEX_SIMPLEX;
771           break;
772         case DMDUP_HORIZONTAL:
773           duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
774           break;
775         case DMDUP_VERTICAL:
776           duplex = GTK_PRINT_DUPLEX_VERTICAL;
777           break;
778         }
779       
780       gtk_print_settings_set_duplex (settings, duplex);
781     }
782   
783   if (devmode->dmFields & DM_COLLATE)
784     gtk_print_settings_set_collate (settings,
785                                     devmode->dmCollate == DMCOLLATE_TRUE);
786   
787   if (devmode->dmFields & DM_MEDIATYPE)
788     {
789       char *media_type;
790       switch (devmode->dmMediaType)
791         {
792         default:
793         case DMMEDIA_STANDARD:
794           media_type = "stationery";
795           break;
796         case DMMEDIA_TRANSPARENCY:
797           media_type = "transparency";
798           break;
799         case DMMEDIA_GLOSSY:
800           media_type = "photographic-glossy";
801           break;
802         }
803       gtk_print_settings_set_media_type (settings, media_type);
804       gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
805     }
806   
807   if (devmode->dmFields & DM_DITHERTYPE)
808     {
809       char *dither;
810       switch (devmode->dmDitherType)
811         {
812         default:
813         case DMDITHER_FINE:
814           dither = "fine";
815           break;
816         case DMDITHER_NONE:
817           dither = "none";
818           break;
819         case DMDITHER_COARSE:
820           dither = "coarse";
821           break;
822         case DMDITHER_LINEART:
823           dither = "lineart";
824           break;
825         case DMDITHER_GRAYSCALE:
826           dither = "grayscale";
827           break;
828         case DMDITHER_ERRORDIFFUSION:
829           dither = "error-diffusion";
830           break;
831         }
832       gtk_print_settings_set_dither (settings, dither);
833       gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
834     }
835   
836   GlobalUnlock (hDevMode);
837 }
838
839 static void
840 dialog_to_print_settings (GtkPrintOperation *op,
841                           LPPRINTDLGEXW printdlgex)
842 {
843   int i;
844   GtkPrintSettings *settings;
845
846   settings = gtk_print_settings_new ();
847
848   gtk_print_settings_set_print_pages (settings,
849                                       GTK_PRINT_PAGES_ALL);
850   if (printdlgex->Flags & PD_CURRENTPAGE)
851     gtk_print_settings_set_print_pages (settings,
852                                         GTK_PRINT_PAGES_CURRENT);
853   else if (printdlgex->Flags & PD_PAGENUMS)
854     gtk_print_settings_set_print_pages (settings,
855                                         GTK_PRINT_PAGES_RANGES);
856
857   if (printdlgex->nPageRanges > 0)
858     {
859       GtkPageRange *ranges;
860       ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
861
862       for (i = 0; i < printdlgex->nPageRanges; i++)
863         {
864           ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
865           ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
866         }
867
868       gtk_print_settings_set_page_ranges (settings, ranges,
869                                           printdlgex->nPageRanges);
870       g_free (ranges);
871     }
872   
873   if (printdlgex->hDevNames != NULL)
874     devnames_to_settings (settings, printdlgex->hDevNames);
875
876   if (printdlgex->hDevMode != NULL)
877     devmode_to_settings (settings, printdlgex->hDevMode);
878   
879   gtk_print_operation_set_print_settings (op, settings);
880 }
881
882 static HANDLE
883 devmode_from_settings (GtkPrintSettings *settings,
884                        GtkPageSetup *page_setup)
885 {
886   HANDLE hDevMode;
887   LPDEVMODEW devmode;
888   char *extras;
889   GtkPaperSize *paper_size;
890   const char *extras_base64;
891   int extras_len;
892   const char *val;
893
894   extras = NULL;
895   extras_len = 0;
896   extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
897   if (extras_base64)
898     extras = g_base64_decode (extras_base64, &extras_len);
899   
900   hDevMode = GlobalAlloc (GMEM_MOVEABLE, 
901                           sizeof (DEVMODEW) + extras_len);
902
903   devmode = GlobalLock (hDevMode);
904
905   memset (devmode, 0, sizeof (DEVMODEW));
906   
907   devmode->dmSpecVersion = DM_SPECVERSION;
908   devmode->dmSize = sizeof (DEVMODEW);
909   
910   devmode->dmDriverExtra = 0;
911   if (extras && extras_len > 0)
912     {
913       devmode->dmDriverExtra = extras_len;
914       memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
915       g_free (extras);
916     }
917   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
918     devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
919   
920   if (page_setup ||
921       gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
922     {
923       GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
924       if (page_setup)
925         orientation = gtk_page_setup_get_orientation (page_setup);
926       devmode->dmFields |= DM_ORIENTATION;
927       devmode->dmOrientation = orientation_to_win32 (orientation);
928     }
929
930   if (page_setup)
931     paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
932   else
933     {
934       int size;
935       if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
936           (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
937         {
938           devmode->dmFields |= DM_PAPERSIZE;
939           devmode->dmPaperSize = size;
940           paper_size = NULL;
941         }
942       else
943         paper_size = gtk_print_settings_get_paper_size (settings);
944     }
945   if (paper_size)
946     {
947       devmode->dmFields |= DM_PAPERSIZE;
948       devmode->dmPaperSize = paper_size_to_win32 (paper_size);
949       if (devmode->dmPaperSize == 0)
950         {
951           devmode->dmPaperSize = DMPAPER_USER;
952           devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
953           devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) / 10.0;
954           devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) / 10.0;
955         }
956       gtk_paper_size_free (paper_size);
957     }
958
959   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
960     {
961       devmode->dmFields |= DM_SCALE;
962       devmode->dmScale = gtk_print_settings_get_scale (settings);
963     }
964   
965   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
966     {
967       devmode->dmFields |= DM_COPIES;
968       devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
969     }
970
971   if (gtk_print_settings_has_key (settings, "win32-default-source"))
972     {
973       devmode->dmFields |= DM_DEFAULTSOURCE;
974       devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
975     }
976   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
977     {
978       devmode->dmFields |= DM_DEFAULTSOURCE;
979       devmode->dmDefaultSource = DMBIN_AUTO;
980
981       val = gtk_print_settings_get_default_source (settings);
982       if (strcmp (val, "auto") == 0)
983         devmode->dmDefaultSource = DMBIN_AUTO;
984       if (strcmp (val, "cassette") == 0)
985         devmode->dmDefaultSource = DMBIN_CASSETTE;
986       if (strcmp (val, "envelope") == 0)
987         devmode->dmDefaultSource = DMBIN_ENVELOPE;
988       if (strcmp (val, "envelope-manual") == 0)
989         devmode->dmDefaultSource = DMBIN_ENVMANUAL;
990       if (strcmp (val, "lower") == 0)
991         devmode->dmDefaultSource = DMBIN_LOWER;
992       if (strcmp (val, "manual") == 0)
993         devmode->dmDefaultSource = DMBIN_MANUAL;
994       if (strcmp (val, "middle") == 0)
995         devmode->dmDefaultSource = DMBIN_MIDDLE;
996       if (strcmp (val, "only-one") == 0)
997         devmode->dmDefaultSource = DMBIN_ONLYONE;
998       if (strcmp (val, "form-source") == 0)
999         devmode->dmDefaultSource = DMBIN_FORMSOURCE;
1000       if (strcmp (val, "large-capacity") == 0)
1001         devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
1002       if (strcmp (val, "large-format") == 0)
1003         devmode->dmDefaultSource = DMBIN_LARGEFMT;
1004       if (strcmp (val, "tractor") == 0)
1005         devmode->dmDefaultSource = DMBIN_TRACTOR;
1006       if (strcmp (val, "small-format") == 0)
1007         devmode->dmDefaultSource = DMBIN_SMALLFMT;
1008     }
1009
1010   if (gtk_print_settings_has_key (settings, "win32-print-quality"))
1011     {
1012       devmode->dmFields |= DM_PRINTQUALITY;
1013       devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
1014     }
1015   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
1016     {
1017       devmode->dmFields |= DM_PRINTQUALITY;
1018       devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
1019     } 
1020   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
1021     {
1022       devmode->dmFields |= DM_PRINTQUALITY;
1023       switch (gtk_print_settings_get_quality (settings))
1024         {
1025         case GTK_PRINT_QUALITY_LOW:
1026           devmode->dmPrintQuality = DMRES_LOW;
1027           break;
1028         case GTK_PRINT_QUALITY_DRAFT:
1029           devmode->dmPrintQuality = DMRES_DRAFT;
1030           break;
1031         default:
1032         case GTK_PRINT_QUALITY_NORMAL:
1033           devmode->dmPrintQuality = DMRES_MEDIUM;
1034           break;
1035         case GTK_PRINT_QUALITY_HIGH:
1036           devmode->dmPrintQuality = DMRES_HIGH;
1037           break;
1038         }
1039     }
1040
1041   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
1042     {
1043       devmode->dmFields |= DM_COLOR;
1044       if (gtk_print_settings_get_use_color (settings))
1045         devmode->dmColor = DMCOLOR_COLOR;
1046       else
1047         devmode->dmColor = DMCOLOR_MONOCHROME;
1048     }
1049
1050   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
1051     {
1052       devmode->dmFields |= DM_DUPLEX;
1053       switch (gtk_print_settings_get_duplex (settings))
1054         {
1055         default:
1056         case GTK_PRINT_DUPLEX_SIMPLEX:
1057           devmode->dmDuplex = DMDUP_SIMPLEX;
1058           break;
1059         case GTK_PRINT_DUPLEX_HORIZONTAL:
1060           devmode->dmDuplex = DMDUP_HORIZONTAL;
1061           break;
1062         case GTK_PRINT_DUPLEX_VERTICAL:
1063           devmode->dmDuplex = DMDUP_VERTICAL;
1064           break;
1065         }
1066     }
1067
1068   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
1069     {
1070       devmode->dmFields |= DM_COLLATE;
1071       if (gtk_print_settings_get_collate (settings))
1072         devmode->dmCollate = DMCOLLATE_TRUE;
1073       else
1074         devmode->dmCollate = DMCOLLATE_FALSE;
1075     }
1076
1077   if (gtk_print_settings_has_key (settings, "win32-media-type"))
1078     {
1079       devmode->dmFields |= DM_MEDIATYPE;
1080       devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
1081     }
1082   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
1083     {
1084       devmode->dmFields |= DM_MEDIATYPE;
1085       devmode->dmMediaType = DMMEDIA_STANDARD;
1086       
1087       val = gtk_print_settings_get_media_type (settings);
1088       if (strcmp (val, "transparency") == 0)
1089         devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
1090       if (strcmp (val, "photographic-glossy") == 0)
1091         devmode->dmMediaType = DMMEDIA_GLOSSY;
1092     }
1093  
1094   if (gtk_print_settings_has_key (settings, "win32-dither-type"))
1095     {
1096       devmode->dmFields |= DM_DITHERTYPE;
1097       devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
1098     }
1099   else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
1100     {
1101       devmode->dmFields |= DM_DITHERTYPE;
1102       devmode->dmDitherType = DMDITHER_FINE;
1103       
1104       val = gtk_print_settings_get_dither (settings);
1105       if (strcmp (val, "none") == 0)
1106         devmode->dmDitherType = DMDITHER_NONE;
1107       if (strcmp (val, "coarse") == 0)
1108         devmode->dmDitherType = DMDITHER_COARSE;
1109       if (strcmp (val, "fine") == 0)
1110         devmode->dmDitherType = DMDITHER_FINE;
1111       if (strcmp (val, "lineart") == 0)
1112         devmode->dmDitherType = DMDITHER_LINEART;
1113       if (strcmp (val, "grayscale") == 0)
1114         devmode->dmDitherType = DMDITHER_GRAYSCALE;
1115       if (strcmp (val, "error-diffusion") == 0)
1116         devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
1117     }
1118   
1119   GlobalUnlock (hDevMode);
1120
1121   return hDevMode;
1122 }
1123
1124 static void
1125 dialog_from_print_settings (GtkPrintOperation *op,
1126                             LPPRINTDLGEXW printdlgex)
1127 {
1128   GtkPrintSettings *settings = op->priv->print_settings;
1129   const char *printer;
1130
1131   if (settings == NULL)
1132     return;
1133
1134   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
1135     {
1136       GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
1137
1138       switch (print_pages)
1139         {
1140         default:
1141         case GTK_PRINT_PAGES_ALL:
1142           printdlgex->Flags |= PD_ALLPAGES;
1143           break;
1144         case GTK_PRINT_PAGES_CURRENT:
1145           printdlgex->Flags |= PD_CURRENTPAGE;
1146           break;
1147         case GTK_PRINT_PAGES_RANGES:
1148           printdlgex->Flags |= PD_PAGENUMS;
1149           break;
1150         }
1151     }
1152   if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
1153     {
1154       GtkPageRange *ranges;
1155       int num_ranges, i;
1156
1157       ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
1158
1159       if (num_ranges > MAX_PAGE_RANGES)
1160         num_ranges = MAX_PAGE_RANGES;
1161
1162       printdlgex->nPageRanges = num_ranges;
1163       for (i = 0; i < num_ranges; i++)
1164         {
1165           printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
1166           printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
1167         }
1168     }
1169   
1170   printer = gtk_print_settings_get_printer (settings);
1171   if (printer)
1172     printdlgex->hDevNames = gtk_print_win32_devnames_from_printer_name (printer);
1173   
1174   printdlgex->hDevMode = devmode_from_settings (settings,
1175                                                 op->priv->default_page_setup);
1176 }
1177
1178 typedef struct {
1179   IPrintDialogCallback iPrintDialogCallback;
1180   gboolean set_hwnd;
1181   int ref_count;
1182 } PrintDialogCallback;
1183
1184
1185 static ULONG STDMETHODCALLTYPE
1186 iprintdialogcallback_addref (IPrintDialogCallback *This)
1187 {
1188   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1189   return ++callback->ref_count;
1190 }
1191
1192 static ULONG STDMETHODCALLTYPE
1193 iprintdialogcallback_release (IPrintDialogCallback *This)
1194 {
1195   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1196   int ref_count = --callback->ref_count;
1197
1198   if (ref_count == 0)
1199     g_free (This);
1200
1201   return ref_count;
1202 }
1203
1204 static HRESULT STDMETHODCALLTYPE
1205 iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
1206                                      REFIID       riid,
1207                                      LPVOID      *ppvObject)
1208 {
1209    if (IsEqualIID (riid, &IID_IUnknown) ||
1210        IsEqualIID (riid, &myIID_IPrintDialogCallback))
1211      {
1212        *ppvObject = This;
1213        IUnknown_AddRef ((IUnknown *)This);
1214        return NOERROR;
1215      }
1216    else
1217      {
1218        *ppvObject = NULL;
1219        return E_NOINTERFACE;
1220      }
1221 }
1222
1223 static HRESULT STDMETHODCALLTYPE
1224 iprintdialogcallback_initdone (IPrintDialogCallback *This)
1225 {
1226   return S_FALSE;
1227 }
1228
1229 static HRESULT STDMETHODCALLTYPE
1230 iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
1231 {
1232   return S_FALSE;
1233 }
1234
1235 static HRESULT STDMETHODCALLTYPE
1236 iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
1237                                     HWND hDlg,
1238                                     UINT uMsg,
1239                                     WPARAM wParam,
1240                                     LPARAM lParam,
1241                                     LRESULT *pResult)
1242 {
1243   PrintDialogCallback *callback = (PrintDialogCallback *)This;
1244
1245   if (!callback->set_hwnd)
1246     {
1247       gdk_win32_set_modal_dialog_libgtk_only (hDlg);
1248       callback->set_hwnd = TRUE;
1249       while (gtk_events_pending ())
1250         gtk_main_iteration ();
1251     }
1252   else if (uMsg == got_gdk_events_message)
1253     {
1254       while (gtk_events_pending ())
1255         gtk_main_iteration ();
1256       *pResult = TRUE;
1257       return S_OK;
1258     }
1259   
1260   *pResult = 0;
1261   return S_FALSE;
1262 }
1263
1264 static IPrintDialogCallbackVtbl ipdc_vtbl = {
1265   iprintdialogcallback_queryinterface,
1266   iprintdialogcallback_addref,
1267   iprintdialogcallback_release,
1268   iprintdialogcallback_initdone,
1269   iprintdialogcallback_selectionchange,
1270   iprintdialogcallback_handlemessage
1271 };
1272
1273 static IPrintDialogCallback *
1274 print_callback_new  (void)
1275 {
1276   PrintDialogCallback *callback;
1277
1278   callback = g_new0 (PrintDialogCallback, 1);
1279   callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
1280   callback->ref_count = 1;
1281   callback->set_hwnd = FALSE;
1282
1283   return &callback->iPrintDialogCallback;
1284 }
1285
1286 static  void
1287 plug_grab_notify (GtkWidget        *widget,
1288                   gboolean          was_grabbed,
1289                   GtkPrintOperation *op)
1290 {
1291   EnableWindow(GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
1292                was_grabbed);
1293 }
1294
1295
1296 static BOOL CALLBACK
1297 pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1298 {
1299   GtkPrintOperation *op;
1300   GtkPrintOperationWin32 *op_win32;
1301   
1302   if (message == WM_INITDIALOG)
1303     {
1304       PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
1305       GtkWidget *plug;
1306
1307       op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
1308       op_win32 = op->priv->platform_data;
1309
1310       SetWindowLongPtrW(wnd, GWLP_USERDATA, (LONG_PTR)op);
1311       
1312       plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
1313       gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
1314       op_win32->embed_widget = plug;
1315       gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
1316       gtk_widget_show (op->priv->custom_widget);
1317       gtk_widget_show (plug);
1318       gdk_window_focus (plug->window, GDK_CURRENT_TIME);
1319
1320       /* This dialog is modal, so we grab the embed widget */
1321       gtk_grab_add (plug);
1322
1323       /* When we lose the grab we need to disable the print dialog */
1324       g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
1325       return FALSE;
1326     }
1327   else if (message == WM_DESTROY)
1328     {
1329       op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
1330       op_win32 = op->priv->platform_data;
1331       
1332       g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
1333       gtk_widget_destroy (op_win32->embed_widget);
1334       op_win32->embed_widget = NULL;
1335       op->priv->custom_widget = NULL;
1336     }
1337   else 
1338     {
1339       op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
1340       op_win32 = op->priv->platform_data;
1341
1342       return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
1343                                                        wnd, message, wparam, lparam);
1344     }
1345   
1346   return FALSE;
1347 }
1348
1349 static HPROPSHEETPAGE
1350 create_application_page (GtkPrintOperation *op)
1351 {
1352   HPROPSHEETPAGE hpage;
1353   PROPSHEETPAGEW page;
1354   DLGTEMPLATE *template;
1355   HGLOBAL htemplate;
1356   LONG base_units;
1357   WORD baseunitX, baseunitY;
1358   WORD *array;
1359   GtkRequisition requisition;
1360   const char *tab_label;
1361
1362   /* Make the template the size of the custom widget size request */
1363   gtk_widget_size_request (op->priv->custom_widget, &requisition);
1364       
1365   base_units = GetDialogBaseUnits();
1366   baseunitX = LOWORD(base_units);
1367   baseunitY = HIWORD(base_units);
1368   
1369   htemplate = GlobalAlloc (GMEM_MOVEABLE, 
1370                            sizeof (DLGTEMPLATE) + sizeof(WORD) * 3);
1371   template = GlobalLock (htemplate);
1372   template->style = WS_CHILDWINDOW | DS_CONTROL;
1373   template->dwExtendedStyle = WS_EX_CONTROLPARENT;
1374   template->cdit = 0;
1375   template->x = MulDiv(0, 4, baseunitX);
1376   template->y = MulDiv(0, 8, baseunitY);
1377   template->cx = MulDiv(requisition.width, 4, baseunitX);
1378   template->cy = MulDiv(requisition.height, 8, baseunitY);
1379   
1380   array = (WORD *) (template+1);
1381   *array++ = 0; /* menu */
1382   *array++ = 0; /* class */
1383   *array++ = 0; /* title */
1384   
1385   memset(&page, 0, sizeof (page));
1386   page.dwSize = sizeof (page);
1387   page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
1388   page.hInstance = GetModuleHandle (NULL);
1389   page.pResource = template;
1390   
1391   tab_label = op->priv->custom_tab_label;
1392   if (tab_label == NULL)
1393     tab_label = g_get_application_name ();
1394   if (tab_label == NULL)
1395     tab_label = _("Application");
1396   page.pszTitle = g_utf8_to_utf16 (tab_label, 
1397                                    -1, NULL, NULL, NULL);
1398   page.pfnDlgProc = pageDlgProc;
1399   page.pfnCallback = NULL;
1400   page.lParam = (LPARAM) op;
1401   hpage = CreatePropertySheetPageW(&page);
1402   
1403   GlobalUnlock (htemplate);
1404   
1405   /* TODO: We're leaking htemplate here... */
1406   
1407   return hpage;
1408 }
1409
1410 static GtkPageSetup *
1411 create_page_setup (GtkPrintOperation *op)
1412 {
1413   GtkPrintOperationPrivate *priv = op->priv;
1414   GtkPageSetup *page_setup;
1415   GtkPrintSettings *settings;
1416   
1417   if (priv->default_page_setup)
1418     page_setup = gtk_page_setup_copy (priv->default_page_setup);
1419   else
1420     page_setup = gtk_page_setup_new ();
1421
1422   settings = priv->print_settings;
1423   if (settings)
1424     {
1425       GtkPaperSize *paper_size;
1426       
1427       if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1428         gtk_page_setup_set_orientation (page_setup,
1429                                         gtk_print_settings_get_orientation (settings));
1430
1431
1432       paper_size = gtk_print_settings_get_paper_size (settings);
1433       if (paper_size)
1434         {
1435           gtk_page_setup_set_paper_size (page_setup, paper_size);
1436           gtk_paper_size_free (paper_size);
1437         }
1438
1439       /* TODO: Margins? */
1440     }
1441   
1442   return page_setup;
1443 }
1444
1445 GtkPrintOperationResult
1446 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
1447                                                   gboolean show_dialog,
1448                                                   GtkWindow *parent,
1449                                                   gboolean *do_print)
1450 {
1451   HRESULT hResult;
1452   LPPRINTDLGEXW printdlgex = NULL;
1453   LPPRINTPAGERANGE page_ranges = NULL;
1454   HWND parentHWnd;
1455   GtkWidget *invisible = NULL;
1456   GtkPrintOperationResult result;
1457   GtkPrintOperationWin32 *op_win32;
1458   GtkPrintOperationPrivate *priv;
1459   IPrintDialogCallback *callback;
1460   HPROPSHEETPAGE prop_page;
1461   
1462   *do_print = FALSE;
1463
1464   priv = op->priv;
1465   
1466   op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1467   priv->platform_data = op_win32;
1468   priv->free_platform_data = (GDestroyNotify) op_win32_free;
1469   
1470   if (parent == NULL)
1471     {
1472       invisible = gtk_invisible_new ();
1473       parentHWnd = get_parent_hwnd (invisible);
1474     }
1475   else 
1476     parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
1477
1478   printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
1479   if (!printdlgex)
1480     {
1481       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1482       g_set_error (&priv->error,
1483                    GTK_PRINT_ERROR,
1484                    GTK_PRINT_ERROR_NOMEM,
1485                    _("Not enough free memory"));
1486       goto out;
1487     }      
1488
1489   printdlgex->lStructSize = sizeof(PRINTDLGEXW);
1490   printdlgex->hwndOwner = parentHWnd;
1491   printdlgex->hDevMode = NULL;
1492   printdlgex->hDevNames = NULL;
1493   printdlgex->hDC = NULL;
1494   printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
1495   if (op->priv->current_page == -1)
1496     printdlgex->Flags |= PD_NOCURRENTPAGE;
1497   printdlgex->Flags2 = 0;
1498   printdlgex->ExclusionFlags = 0;
1499
1500   page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR, 
1501                                                 MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
1502   if (!page_ranges) 
1503     {
1504       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1505       g_set_error (&priv->error,
1506                    GTK_PRINT_ERROR,
1507                    GTK_PRINT_ERROR_NOMEM,
1508                    _("Not enough free memory"));
1509       goto out;
1510     }
1511
1512   printdlgex->nPageRanges = 0;
1513   printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
1514   printdlgex->lpPageRanges = page_ranges;
1515   printdlgex->nMinPage = 1;
1516   if (op->priv->nr_of_pages != -1)
1517     printdlgex->nMaxPage = op->priv->nr_of_pages;
1518   else
1519     printdlgex->nMaxPage = 10000;
1520   printdlgex->nCopies = 1;
1521   printdlgex->hInstance = 0;
1522   printdlgex->lpPrintTemplateName = NULL;
1523   printdlgex->lpCallback = NULL;
1524
1525   g_signal_emit_by_name (op, "create-custom-widget",
1526                          &op->priv->custom_widget);
1527   if (op->priv->custom_widget) {
1528     prop_page = create_application_page (op);
1529     printdlgex->nPropertyPages = 1;
1530     printdlgex->lphPropertyPages = &prop_page;
1531   } else {
1532     printdlgex->nPropertyPages = 0;
1533     printdlgex->lphPropertyPages = NULL;
1534   }
1535   
1536   printdlgex->nStartPage = START_PAGE_GENERAL;
1537   printdlgex->dwResultAction = 0;
1538
1539   dialog_from_print_settings (op, printdlgex);
1540
1541   callback = print_callback_new ();
1542   printdlgex->lpCallback = (IUnknown *)callback;
1543   got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1544
1545   hResult = PrintDlgExW(printdlgex);
1546   IUnknown_Release ((IUnknown *)callback);
1547   gdk_win32_set_modal_dialog_libgtk_only (NULL);
1548
1549   if (hResult != S_OK) 
1550     {
1551       result = GTK_PRINT_OPERATION_RESULT_ERROR;
1552       if (hResult == E_OUTOFMEMORY)
1553         g_set_error (&priv->error,
1554                      GTK_PRINT_ERROR,
1555                      GTK_PRINT_ERROR_NOMEM,
1556                      _("Not enough free memory"));
1557       else if (hResult == E_INVALIDARG)
1558         g_set_error (&priv->error,
1559                      GTK_PRINT_ERROR,
1560                      GTK_PRINT_ERROR_INTERNAL_ERROR,
1561                      _("Invalid argument to PrintDlgEx"));
1562       else if (hResult == E_POINTER)
1563         g_set_error (&priv->error,
1564                      GTK_PRINT_ERROR,
1565                      GTK_PRINT_ERROR_INTERNAL_ERROR,
1566                      _("Invalid pointer to PrintDlgEx"));
1567       else if (hResult == E_HANDLE)
1568         g_set_error (&priv->error,
1569                      GTK_PRINT_ERROR,
1570                      GTK_PRINT_ERROR_INTERNAL_ERROR,
1571                      _("Invalid handle to PrintDlgEx"));
1572       else /* E_FAIL */
1573         g_set_error (&priv->error,
1574                      GTK_PRINT_ERROR,
1575                      GTK_PRINT_ERROR_GENERAL,
1576                      _("Unspecified error"));
1577       goto out;
1578     }
1579
1580   if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
1581       printdlgex->dwResultAction == PD_RESULT_APPLY)
1582     {
1583       result = GTK_PRINT_OPERATION_RESULT_APPLY;
1584       dialog_to_print_settings (op, printdlgex);
1585     }
1586   else
1587     result = GTK_PRINT_OPERATION_RESULT_CANCEL;
1588   
1589   if (printdlgex->dwResultAction == PD_RESULT_PRINT)
1590     {
1591       DOCINFOW docinfo;
1592       int job_id;
1593       double dpi_x, dpi_y;
1594       cairo_t *cr;
1595       GtkPageSetup *page_setup;
1596
1597       priv->print_context = _gtk_print_context_new (op);
1598       page_setup = create_page_setup (op);
1599       _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1600       g_object_unref (page_setup);
1601       
1602       *do_print = TRUE;
1603
1604       op_win32->surface = cairo_win32_surface_create (printdlgex->hDC);
1605       dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
1606       dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
1607
1608       cr = cairo_create (op_win32->surface);
1609       gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1610       cairo_destroy (cr);
1611       
1612       memset( &docinfo, 0, sizeof (DOCINFOW));
1613       docinfo.cbSize = sizeof (DOCINFOW); 
1614       docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
1615       docinfo.lpszOutput = (LPCWSTR) NULL; 
1616       docinfo.lpszDatatype = (LPCWSTR) NULL; 
1617       docinfo.fwType = 0; 
1618
1619       job_id = StartDocW(printdlgex->hDC, &docinfo); 
1620       g_free ((void *)docinfo.lpszDocName);
1621       if (job_id <= 0) 
1622         { 
1623           result = GTK_PRINT_OPERATION_RESULT_ERROR;
1624           g_set_error (&priv->error,
1625                        GTK_PRINT_ERROR,
1626                        GTK_PRINT_ERROR_GENERAL,
1627                      _("Error from StartDoc"));
1628           *do_print = FALSE;
1629           cairo_surface_destroy (op_win32->surface);
1630           op_win32->surface = NULL;
1631           goto out; 
1632         } 
1633       
1634       op_win32->hdc = printdlgex->hDC;
1635       op_win32->devmode = printdlgex->hDevMode;
1636       op_win32->devnames = printdlgex->hDevNames;
1637       op_win32->job_id = job_id;
1638       
1639       op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1640       op->priv->num_page_ranges = 0;
1641       if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1642         op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1643                                                                     &op->priv->num_page_ranges);
1644       op->priv->manual_num_copies = printdlgex->nCopies;
1645       op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
1646       op->priv->manual_reverse = FALSE;
1647       op->priv->manual_orientation = FALSE;
1648       op->priv->manual_scale = 1.0;
1649       op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1650     }
1651
1652   op->priv->start_page = win32_start_page;
1653   op->priv->end_page = win32_end_page;
1654   op->priv->end_run = win32_end_run;
1655   
1656   out:
1657   if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) 
1658     GlobalFree(printdlgex->hDevMode); 
1659
1660   if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) 
1661     GlobalFree(printdlgex->hDevNames); 
1662
1663   if (page_ranges)
1664     GlobalFree (page_ranges);
1665
1666   if (printdlgex)
1667     GlobalFree (printdlgex);
1668
1669   if (invisible)
1670     gtk_widget_destroy (invisible);
1671
1672   return result;
1673 }
1674
1675 void
1676 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
1677                                                       cairo_surface_t   *surface,
1678                                                       GtkWindow         *parent,
1679                                                       const gchar       *filename)
1680 {
1681   HDC dc;
1682   HENHMETAFILE metafile;
1683   
1684   dc = cairo_win32_surface_get_dc (surface);
1685   cairo_surface_destroy (surface);
1686   metafile = CloseEnhMetaFile (dc);
1687   DeleteEnhMetaFile (metafile);
1688   
1689   ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
1690 }
1691
1692 void
1693 _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
1694                                                           cairo_surface_t *surface,
1695                                                           cairo_t *cr)
1696 {
1697   HDC dc = cairo_win32_surface_get_dc (surface);
1698   StartPage (dc);
1699 }
1700
1701 void
1702 _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
1703                                                         cairo_surface_t *surface,
1704                                                         cairo_t *cr)
1705 {
1706   /* TODO: This doesn't actually seem to work.
1707    * Do enhanced metafiles really support multiple pages?
1708    */
1709   HDC dc = cairo_win32_surface_get_dc (surface);
1710   EndPage (dc);
1711 }
1712
1713 cairo_surface_t *
1714 _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
1715                                                               GtkPageSetup      *page_setup,
1716                                                               gdouble           *dpi_x,
1717                                                               gdouble           *dpi_y,
1718                                                               gchar            **target)
1719 {
1720   GtkPaperSize *paper_size;
1721   double w, h;
1722   HDC metafile_dc;
1723   RECT rect;
1724   char *template;
1725   char *filename;
1726   gunichar2 *filename_utf16;
1727   int fd;
1728
1729   template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
1730   fd = g_mkstemp (template);
1731   close(fd);
1732
1733   filename = g_strconcat (template, ".emf", NULL);
1734   g_free (template);
1735   
1736   filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1737   g_free (filename);
1738
1739   paper_size = gtk_page_setup_get_paper_size (page_setup);
1740   w = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
1741   h = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
1742   
1743   rect.left = 0;
1744   rect.right = w*100;
1745   rect.top = 0;
1746   rect.bottom = h*100;
1747   
1748   metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
1749                                     &rect, L"Gtk+\0Print Preview\0\0");
1750   if (metafile_dc == NULL)
1751     {
1752       g_warning ("Can't create metafile");
1753       return NULL;
1754     }
1755
1756   *target = (char *)filename_utf16;
1757   
1758   *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
1759   *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
1760
1761   return cairo_win32_surface_create (metafile_dc);
1762 }
1763
1764 void
1765 _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
1766                                                               GtkPageSetup      *page_setup,
1767                                                               cairo_surface_t   *surface)
1768 {
1769   /* TODO: Implement */
1770 }
1771
1772 GtkPageSetup *
1773 gtk_print_run_page_setup_dialog (GtkWindow        *parent,
1774                                  GtkPageSetup     *page_setup,
1775                                  GtkPrintSettings *settings)
1776 {
1777   LPPAGESETUPDLGW pagesetupdlg = NULL;
1778   BOOL res;
1779   gboolean free_settings;
1780   const char *printer;
1781   GtkPaperSize *paper_size;
1782   DWORD measure_system;
1783   GtkUnit unit;
1784   double scale;
1785
1786   pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
1787   if (!pagesetupdlg)
1788     return NULL;
1789
1790   free_settings = FALSE;
1791   if (settings == NULL)
1792     {
1793       settings = gtk_print_settings_new ();
1794       free_settings = TRUE;
1795     }
1796   
1797   memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
1798
1799   pagesetupdlg->lStructSize = sizeof(PAGESETUPDLGW);
1800
1801   if (parent != NULL)
1802     pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
1803   else
1804     pagesetupdlg->hwndOwner = NULL;
1805
1806   pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
1807   pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup);
1808   pagesetupdlg->hDevNames = NULL;
1809   printer = gtk_print_settings_get_printer (settings);
1810   if (printer)
1811     pagesetupdlg->hDevNames = gtk_print_win32_devnames_from_printer_name (printer);
1812
1813   GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
1814                  (LPWSTR)&measure_system, sizeof (DWORD));
1815
1816   if (measure_system == 0)
1817     {
1818       pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1819       unit = GTK_UNIT_MM;
1820       scale = 100;
1821     }
1822   else
1823     {
1824       pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
1825       unit = GTK_UNIT_INCH;
1826       scale = 1000;
1827     }
1828
1829   /* This is the object we return, we allocate it here so that
1830    * we can use the default page margins */
1831   if (page_setup)
1832     page_setup = gtk_page_setup_copy (page_setup);
1833   else
1834     page_setup = gtk_page_setup_new ();
1835   
1836   pagesetupdlg->Flags |= PSD_MARGINS;
1837   pagesetupdlg->rtMargin.left =
1838     floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
1839   pagesetupdlg->rtMargin.right =
1840     floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
1841   pagesetupdlg->rtMargin.top = 
1842     floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
1843   pagesetupdlg->rtMargin.bottom =
1844     floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
1845
1846   pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
1847   pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
1848   got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1849   
1850   res = PageSetupDlgW (pagesetupdlg);
1851   gdk_win32_set_modal_dialog_libgtk_only (NULL);
1852
1853   if (res)
1854     {  
1855       if (pagesetupdlg->hDevNames != NULL)
1856         devnames_to_settings (settings, pagesetupdlg->hDevNames);
1857
1858       if (pagesetupdlg->hDevMode != NULL)
1859         devmode_to_settings (settings, pagesetupdlg->hDevMode);
1860     }
1861   
1862   if (free_settings)
1863     g_object_unref (settings);
1864
1865   if (res)
1866     {
1867       gtk_page_setup_set_orientation (page_setup, 
1868                                       gtk_print_settings_get_orientation (settings));
1869       paper_size = gtk_print_settings_get_paper_size (settings);
1870       if (paper_size)
1871         {
1872           gtk_page_setup_set_paper_size (page_setup, paper_size);
1873           gtk_paper_size_free (paper_size);
1874         }
1875
1876       if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
1877         {
1878           unit = GTK_UNIT_MM;
1879           scale = 100;
1880         }
1881       else
1882         {
1883           unit = GTK_UNIT_INCH;
1884           scale = 1000;
1885         }
1886
1887       gtk_page_setup_set_left_margin (page_setup,
1888                                       pagesetupdlg->rtMargin.left / scale,
1889                                       unit);
1890       gtk_page_setup_set_right_margin (page_setup,
1891                                        pagesetupdlg->rtMargin.right / scale,
1892                                        unit);
1893       gtk_page_setup_set_top_margin (page_setup,
1894                                      pagesetupdlg->rtMargin.top / scale,
1895                                      unit);
1896       gtk_page_setup_set_bottom_margin (page_setup,
1897                                         pagesetupdlg->rtMargin.bottom / scale,
1898                                         unit);
1899     }
1900   
1901   return page_setup;
1902 }
1903
1904 void
1905 gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
1906                                        GtkPageSetup         *page_setup,
1907                                        GtkPrintSettings     *settings,
1908                                        GtkPageSetupDoneFunc  done_cb,
1909                                        gpointer              data)
1910 {
1911   GtkPageSetup *new_page_setup;
1912
1913   new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
1914   done_cb (new_page_setup, data);
1915   g_object_unref (new_page_setup);
1916 }
1917
1918 #define __GTK_PRINT_OPERATION_WIN32_C__
1919 #include "gtkaliasdef.c"