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