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