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