1 /* GTK - The GIMP Toolkit
2 * gtkprintoperation-win32.c: Print Operation Details for Win32
3 * Copyright (C) 2006, Red Hat, Inc.
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.
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.
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.
22 #define _WIN32_WINNT 0x0500
23 #define WINVER _WIN32_WINNT
36 #include <cairo-win32.h>
38 #include "gtkprintoperation-private.h"
39 #include "gtkprint-win32.h"
41 #include "gtkinvisible.h"
45 #include "gtkwin32embedwidget.h"
48 #define MAX_PAGE_RANGES 20
49 #define STATUS_POLLING_TIME 2000
51 #ifndef JOB_STATUS_RESTART
52 #define JOB_STATUS_RESTART 0x800
55 #ifndef JOB_STATUS_COMPLETE
56 #define JOB_STATUS_COMPLETE 0x1000
67 cairo_surface_t *surface;
68 GtkWidget *embed_widget;
69 } GtkPrintOperationWin32;
71 static void win32_poll_status (GtkPrintOperation *op);
73 static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
75 #if !defined (_MSC_VER) && !defined (MINGW64) && !defined (__MINGW64)
77 #define INTERFACE IPrintDialogCallback
78 DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
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;
89 static UINT got_gdk_events_message;
92 run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
94 if (uiMsg == WM_INITDIALOG)
96 gdk_win32_set_modal_dialog_libgtk_only (hdlg);
97 while (gtk_events_pending ())
98 gtk_main_iteration ();
100 else if (uiMsg == got_gdk_events_message)
102 while (gtk_events_pending ())
103 gtk_main_iteration ();
109 static GtkPageOrientation
110 orientation_from_win32 (short orientation)
112 if (orientation == DMORIENT_LANDSCAPE)
113 return GTK_PAGE_ORIENTATION_LANDSCAPE;
114 return GTK_PAGE_ORIENTATION_PORTRAIT;
118 orientation_to_win32 (GtkPageOrientation orientation)
120 if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
121 orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
122 return DMORIENT_LANDSCAPE;
123 return DMORIENT_PORTRAIT;
126 static GtkPaperSize *
127 paper_size_from_win32 (short size)
133 case DMPAPER_LETTER_TRANSVERSE:
135 case DMPAPER_LETTERSMALL:
138 case DMPAPER_TABLOID:
145 case DMPAPER_STATEMENT:
148 case DMPAPER_EXECUTIVE:
149 name = "na_executive";
152 case DMPAPER_A3_TRANSVERSE:
156 case DMPAPER_A4SMALL:
157 case DMPAPER_A4_TRANSVERSE:
161 case DMPAPER_A5_TRANSVERSE:
168 case DMPAPER_B5_TRANSVERSE:
184 name = "na_number-9";
187 name = "na_number-10";
190 name = "na_number-11";
193 name = "na_number-12";
196 name = "na_number-14";
222 case DMPAPER_ENV_C65:
234 case DMPAPER_ENV_ITALY:
237 case DMPAPER_ENV_MONARCH:
240 case DMPAPER_ENV_PERSONAL:
241 name = "na_personal";
243 case DMPAPER_FANFOLD_US:
244 name = "na_fanfold-us";
246 case DMPAPER_FANFOLD_STD_GERMAN:
247 name = "na_fanfold-eur";
249 case DMPAPER_FANFOLD_LGL_GERMAN:
250 name = "na_foolscap";
255 case DMPAPER_JAPANESE_POSTCARD:
264 case DMPAPER_ENV_INVITE:
267 case DMPAPER_LETTER_EXTRA:
268 case DMPAPER_LETTER_EXTRA_TRANSVERSE:
269 name = "na_letter-extra";
271 case DMPAPER_LEGAL_EXTRA:
272 name = "na_legal-extra";
274 case DMPAPER_TABLOID_EXTRA:
277 case DMPAPER_A4_EXTRA:
278 name = "iso_a4-extra";
283 case DMPAPER_LETTER_PLUS:
284 name = "na_letter-plus";
286 case DMPAPER_A3_EXTRA:
287 case DMPAPER_A3_EXTRA_TRANSVERSE:
288 name = "iso_a3-extra";
290 case DMPAPER_A5_EXTRA:
291 name = "iso_a5-extra";
293 case DMPAPER_B5_EXTRA:
294 name = "iso_b5-extra";
306 return gtk_paper_size_new (name);
312 paper_size_to_win32 (GtkPaperSize *paper_size)
316 if (gtk_paper_size_is_custom (paper_size))
319 format = gtk_paper_size_get_name (paper_size);
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)
333 if (strcmp (format, "iso_a3") == 0)
335 if (strcmp (format, "iso_a4") == 0)
337 if (strcmp (format, "iso_a5") == 0)
339 if (strcmp (format, "iso_b4") == 0)
341 if (strcmp (format, "iso_b5") == 0)
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)
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;
420 get_default_printer (void)
422 wchar_t *win32_printer_name = NULL;
423 gchar *printer_name = NULL;
426 GetDefaultPrinterW (NULL, &needed);
427 win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
428 if (!GetDefaultPrinterW (win32_printer_name, &needed))
430 g_free (win32_printer_name);
433 printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
434 g_free (win32_printer_name);
440 win32_start_page (GtkPrintOperation *op,
441 GtkPrintContext *print_context,
442 GtkPageSetup *page_setup)
444 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
446 GtkPaperSize *paper_size;
449 devmode = GlobalLock (op_win32->devmode);
451 devmode->dmFields |= DM_ORIENTATION;
452 devmode->dmOrientation =
453 orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
455 paper_size = gtk_page_setup_get_paper_size (page_setup);
456 devmode->dmFields |= DM_PAPERSIZE;
457 devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
458 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
459 if (devmode->dmPaperSize == 0)
461 devmode->dmPaperSize = DMPAPER_USER;
462 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
464 /* Lengths in DEVMODE are in tenths of a millimeter */
465 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
466 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
469 ResetDCW (op_win32->hdc, devmode);
471 GlobalUnlock (op_win32->devmode);
473 x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
474 y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
475 cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
477 StartPage (op_win32->hdc);
481 win32_end_page (GtkPrintOperation *op,
482 GtkPrintContext *print_context)
484 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
486 cairo_surface_show_page (op_win32->surface);
488 EndPage (op_win32->hdc);
492 win32_poll_status_timeout (GtkPrintOperation *op)
494 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
496 op_win32->timeout_id = 0;
497 /* We need to ref this, as setting the status to finished
498 might unref the object */
500 win32_poll_status (op);
502 if (!gtk_print_operation_is_finished (op))
503 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
504 (GSourceFunc)win32_poll_status_timeout,
512 win32_end_run (GtkPrintOperation *op,
516 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
518 HANDLE printerHandle = 0;
520 cairo_surface_finish (op_win32->surface);
522 EndDoc (op_win32->hdc);
524 if (op->priv->track_print_status)
526 devnames = GlobalLock (op_win32->devnames);
527 if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
528 &printerHandle, NULL))
530 GlobalUnlock (op_win32->devnames);
533 GlobalFree (op_win32->devmode);
534 GlobalFree (op_win32->devnames);
536 cairo_surface_destroy (op_win32->surface);
537 op_win32->surface = NULL;
539 DeleteDC (op_win32->hdc);
541 if (printerHandle != 0)
543 op_win32->printerHandle = printerHandle;
544 win32_poll_status (op);
545 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
546 (GSourceFunc)win32_poll_status_timeout,
550 /* Dunno what happened, pretend its finished */
551 _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
555 win32_poll_status (GtkPrintOperation *op)
557 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
560 JOB_INFO_1W *job_info;
561 GtkPrintStatus status;
565 GetJobW (op_win32->printerHandle, op_win32->job_id,
566 1,(LPBYTE)NULL, 0, &needed);
567 data = g_malloc (needed);
568 ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
569 1, (LPBYTE)data, needed, &needed);
575 job_info = (JOB_INFO_1W *)data;
576 win32_status = job_info->Status;
578 if (job_info->pStatus)
579 status_str = g_utf16_to_utf8 (job_info->pStatus,
580 -1, NULL, NULL, NULL);
583 (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
584 status = GTK_PRINT_STATUS_FINISHED;
585 else if (win32_status &
586 (JOB_STATUS_OFFLINE |
587 JOB_STATUS_PAPEROUT |
589 JOB_STATUS_USER_INTERVENTION))
591 status = GTK_PRINT_STATUS_PENDING_ISSUE;
592 if (status_str == NULL)
594 if (win32_status & JOB_STATUS_OFFLINE)
595 status_str = g_strdup (_("Printer offline"));
596 else if (win32_status & JOB_STATUS_PAPEROUT)
597 status_str = g_strdup (_("Out of paper"));
598 else if (win32_status & JOB_STATUS_PAUSED)
599 status_str = g_strdup (_("Paused"));
600 else if (win32_status & JOB_STATUS_USER_INTERVENTION)
601 status_str = g_strdup (_("Need user intervention"));
604 else if (win32_status &
605 (JOB_STATUS_BLOCKED_DEVQ |
608 status = GTK_PRINT_STATUS_FINISHED_ABORTED;
609 else if (win32_status &
610 (JOB_STATUS_SPOOLING |
611 JOB_STATUS_DELETING))
612 status = GTK_PRINT_STATUS_PENDING;
613 else if (win32_status & JOB_STATUS_PRINTING)
614 status = GTK_PRINT_STATUS_PRINTING;
616 status = GTK_PRINT_STATUS_FINISHED;
619 status = GTK_PRINT_STATUS_FINISHED;
623 _gtk_print_operation_set_status (op, status, status_str);
629 op_win32_free (GtkPrintOperationWin32 *op_win32)
631 if (op_win32->printerHandle)
632 ClosePrinter (op_win32->printerHandle);
633 if (op_win32->timeout_id != 0)
634 g_source_remove (op_win32->timeout_id);
639 get_parent_hwnd (GtkWidget *widget)
641 gtk_widget_realize (widget);
642 return gdk_win32_drawable_get_handle (widget->window);
646 devnames_to_settings (GtkPrintSettings *settings,
649 GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
650 gtk_print_settings_set_printer (settings, devnames->device);
651 gtk_print_win32_devnames_free (devnames);
655 devmode_to_settings (GtkPrintSettings *settings,
660 devmode = GlobalLock (hDevMode);
662 gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
663 devmode->dmDriverVersion);
664 if (devmode->dmDriverExtra != 0)
666 char *extra = g_base64_encode (((char *)devmode) + sizeof (DEVMODEW),
667 devmode->dmDriverExtra);
668 gtk_print_settings_set (settings,
669 GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
674 if (devmode->dmFields & DM_ORIENTATION)
675 gtk_print_settings_set_orientation (settings,
676 orientation_from_win32 (devmode->dmOrientation));
679 if (devmode->dmFields & DM_PAPERSIZE &&
680 devmode->dmPaperSize != 0)
682 GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
685 gtk_print_settings_set_paper_size (settings, paper_size);
686 gtk_paper_size_free (paper_size);
688 gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
690 else if ((devmode->dmFields & DM_PAPERSIZE &&
691 devmode->dmPaperSize == 0) ||
692 ((devmode->dmFields & DM_PAPERWIDTH) &&
693 (devmode->dmFields & DM_PAPERLENGTH)))
695 GtkPaperSize *paper_size;
696 char *form_name = NULL;
697 if (devmode->dmFields & DM_FORMNAME)
698 form_name = g_utf16_to_utf8 (devmode->dmFormName,
699 -1, NULL, NULL, NULL);
700 if (form_name == NULL || form_name[0] == 0)
701 form_name = g_strdup (_("Custom size"));
703 /* Lengths in DEVMODE are in tenths of a millimeter */
704 paper_size = gtk_paper_size_new_custom (form_name,
706 devmode->dmPaperWidth / 10.0,
707 devmode->dmPaperLength / 10.0,
709 gtk_print_settings_set_paper_size (settings, paper_size);
710 gtk_paper_size_free (paper_size);
713 if (devmode->dmFields & DM_SCALE)
714 gtk_print_settings_set_scale (settings, devmode->dmScale);
716 if (devmode->dmFields & DM_COPIES)
717 gtk_print_settings_set_n_copies (settings,
720 if (devmode->dmFields & DM_DEFAULTSOURCE)
723 switch (devmode->dmDefaultSource)
735 case DMBIN_ENVMANUAL:
736 source = "envelope-manual";
750 case DMBIN_FORMSOURCE:
751 source = "form-source";
753 case DMBIN_LARGECAPACITY:
754 source = "large-capacity";
757 source = "large-format";
763 source = "small-format";
766 gtk_print_settings_set_default_source (settings, source);
767 gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
770 if (devmode->dmFields & DM_PRINTQUALITY)
772 GtkPrintQuality quality;
773 switch (devmode->dmPrintQuality)
776 quality = GTK_PRINT_QUALITY_LOW;
779 quality = GTK_PRINT_QUALITY_NORMAL;
783 quality = GTK_PRINT_QUALITY_HIGH;
786 quality = GTK_PRINT_QUALITY_DRAFT;
789 gtk_print_settings_set_quality (settings, quality);
790 gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
793 if (devmode->dmFields & DM_COLOR)
794 gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
796 if (devmode->dmFields & DM_DUPLEX)
798 GtkPrintDuplex duplex;
799 switch (devmode->dmDuplex)
803 duplex = GTK_PRINT_DUPLEX_SIMPLEX;
805 case DMDUP_HORIZONTAL:
806 duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
809 duplex = GTK_PRINT_DUPLEX_VERTICAL;
813 gtk_print_settings_set_duplex (settings, duplex);
816 if (devmode->dmFields & DM_COLLATE)
817 gtk_print_settings_set_collate (settings,
818 devmode->dmCollate == DMCOLLATE_TRUE);
820 if (devmode->dmFields & DM_MEDIATYPE)
823 switch (devmode->dmMediaType)
826 case DMMEDIA_STANDARD:
827 media_type = "stationery";
829 case DMMEDIA_TRANSPARENCY:
830 media_type = "transparency";
833 media_type = "photographic-glossy";
836 gtk_print_settings_set_media_type (settings, media_type);
837 gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
840 if (devmode->dmFields & DM_DITHERTYPE)
843 switch (devmode->dmDitherType)
852 case DMDITHER_COARSE:
855 case DMDITHER_LINEART:
858 case DMDITHER_GRAYSCALE:
859 dither = "grayscale";
861 case DMDITHER_ERRORDIFFUSION:
862 dither = "error-diffusion";
865 gtk_print_settings_set_dither (settings, dither);
866 gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
869 GlobalUnlock (hDevMode);
873 dialog_to_print_settings (GtkPrintOperation *op,
874 LPPRINTDLGEXW printdlgex)
877 GtkPrintSettings *settings;
879 settings = gtk_print_settings_new ();
881 gtk_print_settings_set_print_pages (settings,
882 GTK_PRINT_PAGES_ALL);
883 if (printdlgex->Flags & PD_CURRENTPAGE)
884 gtk_print_settings_set_print_pages (settings,
885 GTK_PRINT_PAGES_CURRENT);
886 else if (printdlgex->Flags & PD_PAGENUMS)
887 gtk_print_settings_set_print_pages (settings,
888 GTK_PRINT_PAGES_RANGES);
890 if (printdlgex->nPageRanges > 0)
892 GtkPageRange *ranges;
893 ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
895 for (i = 0; i < printdlgex->nPageRanges; i++)
897 ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
898 ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
901 gtk_print_settings_set_page_ranges (settings, ranges,
902 printdlgex->nPageRanges);
906 if (printdlgex->hDevNames != NULL)
907 devnames_to_settings (settings, printdlgex->hDevNames);
909 if (printdlgex->hDevMode != NULL)
910 devmode_to_settings (settings, printdlgex->hDevMode);
912 gtk_print_operation_set_print_settings (op, settings);
916 devmode_from_settings (GtkPrintSettings *settings,
917 GtkPageSetup *page_setup)
922 GtkPaperSize *paper_size;
923 const char *extras_base64;
929 extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
931 extras = g_base64_decode (extras_base64, &extras_len);
933 hDevMode = GlobalAlloc (GMEM_MOVEABLE,
934 sizeof (DEVMODEW) + extras_len);
936 devmode = GlobalLock (hDevMode);
938 memset (devmode, 0, sizeof (DEVMODEW));
940 devmode->dmSpecVersion = DM_SPECVERSION;
941 devmode->dmSize = sizeof (DEVMODEW);
943 devmode->dmDriverExtra = 0;
944 if (extras && extras_len > 0)
946 devmode->dmDriverExtra = extras_len;
947 memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
950 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
951 devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
954 gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
956 GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
958 orientation = gtk_page_setup_get_orientation (page_setup);
959 devmode->dmFields |= DM_ORIENTATION;
960 devmode->dmOrientation = orientation_to_win32 (orientation);
964 paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
968 if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
969 (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
971 devmode->dmFields |= DM_PAPERSIZE;
972 devmode->dmPaperSize = size;
976 paper_size = gtk_print_settings_get_paper_size (settings);
980 devmode->dmFields |= DM_PAPERSIZE;
981 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
982 if (devmode->dmPaperSize == 0)
984 devmode->dmPaperSize = DMPAPER_USER;
985 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
987 /* Lengths in DEVMODE are in tenths of a millimeter */
988 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
989 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
991 gtk_paper_size_free (paper_size);
994 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
996 devmode->dmFields |= DM_SCALE;
997 devmode->dmScale = gtk_print_settings_get_scale (settings);
1000 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
1002 devmode->dmFields |= DM_COPIES;
1003 devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
1006 if (gtk_print_settings_has_key (settings, "win32-default-source"))
1008 devmode->dmFields |= DM_DEFAULTSOURCE;
1009 devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
1011 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
1013 devmode->dmFields |= DM_DEFAULTSOURCE;
1014 devmode->dmDefaultSource = DMBIN_AUTO;
1016 val = gtk_print_settings_get_default_source (settings);
1017 if (strcmp (val, "auto") == 0)
1018 devmode->dmDefaultSource = DMBIN_AUTO;
1019 if (strcmp (val, "cassette") == 0)
1020 devmode->dmDefaultSource = DMBIN_CASSETTE;
1021 if (strcmp (val, "envelope") == 0)
1022 devmode->dmDefaultSource = DMBIN_ENVELOPE;
1023 if (strcmp (val, "envelope-manual") == 0)
1024 devmode->dmDefaultSource = DMBIN_ENVMANUAL;
1025 if (strcmp (val, "lower") == 0)
1026 devmode->dmDefaultSource = DMBIN_LOWER;
1027 if (strcmp (val, "manual") == 0)
1028 devmode->dmDefaultSource = DMBIN_MANUAL;
1029 if (strcmp (val, "middle") == 0)
1030 devmode->dmDefaultSource = DMBIN_MIDDLE;
1031 if (strcmp (val, "only-one") == 0)
1032 devmode->dmDefaultSource = DMBIN_ONLYONE;
1033 if (strcmp (val, "form-source") == 0)
1034 devmode->dmDefaultSource = DMBIN_FORMSOURCE;
1035 if (strcmp (val, "large-capacity") == 0)
1036 devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
1037 if (strcmp (val, "large-format") == 0)
1038 devmode->dmDefaultSource = DMBIN_LARGEFMT;
1039 if (strcmp (val, "tractor") == 0)
1040 devmode->dmDefaultSource = DMBIN_TRACTOR;
1041 if (strcmp (val, "small-format") == 0)
1042 devmode->dmDefaultSource = DMBIN_SMALLFMT;
1045 if (gtk_print_settings_has_key (settings, "win32-print-quality"))
1047 devmode->dmFields |= DM_PRINTQUALITY;
1048 devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
1050 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
1052 devmode->dmFields |= DM_PRINTQUALITY;
1053 devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
1055 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
1057 devmode->dmFields |= DM_PRINTQUALITY;
1058 switch (gtk_print_settings_get_quality (settings))
1060 case GTK_PRINT_QUALITY_LOW:
1061 devmode->dmPrintQuality = DMRES_LOW;
1063 case GTK_PRINT_QUALITY_DRAFT:
1064 devmode->dmPrintQuality = DMRES_DRAFT;
1067 case GTK_PRINT_QUALITY_NORMAL:
1068 devmode->dmPrintQuality = DMRES_MEDIUM;
1070 case GTK_PRINT_QUALITY_HIGH:
1071 devmode->dmPrintQuality = DMRES_HIGH;
1076 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
1078 devmode->dmFields |= DM_COLOR;
1079 if (gtk_print_settings_get_use_color (settings))
1080 devmode->dmColor = DMCOLOR_COLOR;
1082 devmode->dmColor = DMCOLOR_MONOCHROME;
1085 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
1087 devmode->dmFields |= DM_DUPLEX;
1088 switch (gtk_print_settings_get_duplex (settings))
1091 case GTK_PRINT_DUPLEX_SIMPLEX:
1092 devmode->dmDuplex = DMDUP_SIMPLEX;
1094 case GTK_PRINT_DUPLEX_HORIZONTAL:
1095 devmode->dmDuplex = DMDUP_HORIZONTAL;
1097 case GTK_PRINT_DUPLEX_VERTICAL:
1098 devmode->dmDuplex = DMDUP_VERTICAL;
1103 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
1105 devmode->dmFields |= DM_COLLATE;
1106 if (gtk_print_settings_get_collate (settings))
1107 devmode->dmCollate = DMCOLLATE_TRUE;
1109 devmode->dmCollate = DMCOLLATE_FALSE;
1112 if (gtk_print_settings_has_key (settings, "win32-media-type"))
1114 devmode->dmFields |= DM_MEDIATYPE;
1115 devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
1117 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
1119 devmode->dmFields |= DM_MEDIATYPE;
1120 devmode->dmMediaType = DMMEDIA_STANDARD;
1122 val = gtk_print_settings_get_media_type (settings);
1123 if (strcmp (val, "transparency") == 0)
1124 devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
1125 if (strcmp (val, "photographic-glossy") == 0)
1126 devmode->dmMediaType = DMMEDIA_GLOSSY;
1129 if (gtk_print_settings_has_key (settings, "win32-dither-type"))
1131 devmode->dmFields |= DM_DITHERTYPE;
1132 devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
1134 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
1136 devmode->dmFields |= DM_DITHERTYPE;
1137 devmode->dmDitherType = DMDITHER_FINE;
1139 val = gtk_print_settings_get_dither (settings);
1140 if (strcmp (val, "none") == 0)
1141 devmode->dmDitherType = DMDITHER_NONE;
1142 if (strcmp (val, "coarse") == 0)
1143 devmode->dmDitherType = DMDITHER_COARSE;
1144 if (strcmp (val, "fine") == 0)
1145 devmode->dmDitherType = DMDITHER_FINE;
1146 if (strcmp (val, "lineart") == 0)
1147 devmode->dmDitherType = DMDITHER_LINEART;
1148 if (strcmp (val, "grayscale") == 0)
1149 devmode->dmDitherType = DMDITHER_GRAYSCALE;
1150 if (strcmp (val, "error-diffusion") == 0)
1151 devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
1154 GlobalUnlock (hDevMode);
1160 dialog_from_print_settings (GtkPrintOperation *op,
1161 LPPRINTDLGEXW printdlgex)
1163 GtkPrintSettings *settings = op->priv->print_settings;
1164 const char *printer;
1166 if (settings == NULL)
1169 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
1171 GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
1173 switch (print_pages)
1176 case GTK_PRINT_PAGES_ALL:
1177 printdlgex->Flags |= PD_ALLPAGES;
1179 case GTK_PRINT_PAGES_CURRENT:
1180 printdlgex->Flags |= PD_CURRENTPAGE;
1182 case GTK_PRINT_PAGES_RANGES:
1183 printdlgex->Flags |= PD_PAGENUMS;
1187 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
1189 GtkPageRange *ranges;
1192 ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
1194 if (num_ranges > MAX_PAGE_RANGES)
1195 num_ranges = MAX_PAGE_RANGES;
1197 printdlgex->nPageRanges = num_ranges;
1198 for (i = 0; i < num_ranges; i++)
1200 printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
1201 printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
1205 printer = gtk_print_settings_get_printer (settings);
1207 printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1209 printdlgex->hDevMode = devmode_from_settings (settings,
1210 op->priv->default_page_setup);
1214 IPrintDialogCallback iPrintDialogCallback;
1217 } PrintDialogCallback;
1220 static ULONG STDMETHODCALLTYPE
1221 iprintdialogcallback_addref (IPrintDialogCallback *This)
1223 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1224 return ++callback->ref_count;
1227 static ULONG STDMETHODCALLTYPE
1228 iprintdialogcallback_release (IPrintDialogCallback *This)
1230 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1231 int ref_count = --callback->ref_count;
1239 static HRESULT STDMETHODCALLTYPE
1240 iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
1244 if (IsEqualIID (riid, &IID_IUnknown) ||
1245 IsEqualIID (riid, &myIID_IPrintDialogCallback))
1248 IUnknown_AddRef ((IUnknown *)This);
1254 return E_NOINTERFACE;
1258 static HRESULT STDMETHODCALLTYPE
1259 iprintdialogcallback_initdone (IPrintDialogCallback *This)
1264 static HRESULT STDMETHODCALLTYPE
1265 iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
1270 static HRESULT STDMETHODCALLTYPE
1271 iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
1278 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1280 if (!callback->set_hwnd)
1282 gdk_win32_set_modal_dialog_libgtk_only (hDlg);
1283 callback->set_hwnd = TRUE;
1284 while (gtk_events_pending ())
1285 gtk_main_iteration ();
1287 else if (uMsg == got_gdk_events_message)
1289 while (gtk_events_pending ())
1290 gtk_main_iteration ();
1299 static IPrintDialogCallbackVtbl ipdc_vtbl = {
1300 iprintdialogcallback_queryinterface,
1301 iprintdialogcallback_addref,
1302 iprintdialogcallback_release,
1303 iprintdialogcallback_initdone,
1304 iprintdialogcallback_selectionchange,
1305 iprintdialogcallback_handlemessage
1308 static IPrintDialogCallback *
1309 print_callback_new (void)
1311 PrintDialogCallback *callback;
1313 callback = g_new0 (PrintDialogCallback, 1);
1314 callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
1315 callback->ref_count = 1;
1316 callback->set_hwnd = FALSE;
1318 return &callback->iPrintDialogCallback;
1322 plug_grab_notify (GtkWidget *widget,
1323 gboolean was_grabbed,
1324 GtkPrintOperation *op)
1326 EnableWindow (GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
1331 static BOOL CALLBACK
1332 pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1334 GtkPrintOperation *op;
1335 GtkPrintOperationWin32 *op_win32;
1337 if (message == WM_INITDIALOG)
1339 PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
1342 op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
1343 op_win32 = op->priv->platform_data;
1345 SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
1347 plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
1348 gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
1349 op_win32->embed_widget = plug;
1350 gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
1351 gtk_widget_show (op->priv->custom_widget);
1352 gtk_widget_show (plug);
1353 gdk_window_focus (plug->window, GDK_CURRENT_TIME);
1355 /* This dialog is modal, so we grab the embed widget */
1356 gtk_grab_add (plug);
1358 /* When we lose the grab we need to disable the print dialog */
1359 g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
1362 else if (message == WM_DESTROY)
1364 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1365 op_win32 = op->priv->platform_data;
1367 g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
1368 gtk_widget_destroy (op_win32->embed_widget);
1369 op_win32->embed_widget = NULL;
1370 op->priv->custom_widget = NULL;
1374 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1375 op_win32 = op->priv->platform_data;
1377 return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
1378 wnd, message, wparam, lparam);
1384 static HPROPSHEETPAGE
1385 create_application_page (GtkPrintOperation *op)
1387 HPROPSHEETPAGE hpage;
1388 PROPSHEETPAGEW page;
1389 DLGTEMPLATE *template;
1392 WORD baseunitX, baseunitY;
1394 GtkRequisition requisition;
1395 const char *tab_label;
1397 /* Make the template the size of the custom widget size request */
1398 gtk_widget_size_request (op->priv->custom_widget, &requisition);
1400 base_units = GetDialogBaseUnits ();
1401 baseunitX = LOWORD (base_units);
1402 baseunitY = HIWORD (base_units);
1404 htemplate = GlobalAlloc (GMEM_MOVEABLE,
1405 sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
1406 template = GlobalLock (htemplate);
1407 template->style = WS_CHILDWINDOW | DS_CONTROL;
1408 template->dwExtendedStyle = WS_EX_CONTROLPARENT;
1410 template->x = MulDiv (0, 4, baseunitX);
1411 template->y = MulDiv (0, 8, baseunitY);
1412 template->cx = MulDiv (requisition.width, 4, baseunitX);
1413 template->cy = MulDiv (requisition.height, 8, baseunitY);
1415 array = (WORD *) (template+1);
1416 *array++ = 0; /* menu */
1417 *array++ = 0; /* class */
1418 *array++ = 0; /* title */
1420 memset (&page, 0, sizeof (page));
1421 page.dwSize = sizeof (page);
1422 page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
1423 page.hInstance = GetModuleHandle (NULL);
1424 page.pResource = template;
1426 tab_label = op->priv->custom_tab_label;
1427 if (tab_label == NULL)
1428 tab_label = g_get_application_name ();
1429 if (tab_label == NULL)
1430 tab_label = _("Application");
1431 page.pszTitle = g_utf8_to_utf16 (tab_label,
1432 -1, NULL, NULL, NULL);
1433 page.pfnDlgProc = pageDlgProc;
1434 page.pfnCallback = NULL;
1435 page.lParam = (LPARAM) op;
1436 hpage = CreatePropertySheetPageW (&page);
1438 GlobalUnlock (htemplate);
1440 /* TODO: We're leaking htemplate here... */
1445 static GtkPageSetup *
1446 create_page_setup (GtkPrintOperation *op)
1448 GtkPrintOperationPrivate *priv = op->priv;
1449 GtkPageSetup *page_setup;
1450 GtkPrintSettings *settings;
1452 if (priv->default_page_setup)
1453 page_setup = gtk_page_setup_copy (priv->default_page_setup);
1455 page_setup = gtk_page_setup_new ();
1457 settings = priv->print_settings;
1460 GtkPaperSize *paper_size;
1462 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1463 gtk_page_setup_set_orientation (page_setup,
1464 gtk_print_settings_get_orientation (settings));
1467 paper_size = gtk_print_settings_get_paper_size (settings);
1470 gtk_page_setup_set_paper_size (page_setup, paper_size);
1471 gtk_paper_size_free (paper_size);
1474 /* TODO: Margins? */
1480 GtkPrintOperationResult
1481 gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
1484 GtkPrintOperationResult result;
1485 GtkPrintOperationWin32 *op_win32;
1486 GtkPrintOperationPrivate *priv;
1487 GtkPrintSettings *settings;
1488 GtkPageSetup *page_setup;
1490 HGLOBAL hDevMode = NULL;
1491 HGLOBAL hDevNames = NULL;
1493 const char *printer = NULL;
1494 double dpi_x, dpi_y;
1503 settings = priv->print_settings;
1505 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1506 priv->platform_data = op_win32;
1507 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1508 printer = gtk_print_settings_get_printer (settings);
1512 /* No printer selected. Get the system default printer and store
1515 gchar *tmp_printer = get_default_printer ();
1518 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1519 g_set_error_literal (&priv->error,
1521 GTK_PRINT_ERROR_INTERNAL_ERROR,
1522 _("No printer found"));
1525 gtk_print_settings_set_printer (settings, tmp_printer);
1526 printer = gtk_print_settings_get_printer (settings);
1527 g_free (tmp_printer);
1530 hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1531 hDevMode = devmode_from_settings (settings, op->priv->default_page_setup);
1533 /* Create a printer DC for the print settings and page setup provided. */
1534 pdn = GlobalLock (hDevNames);
1535 pdm = GlobalLock (hDevMode);
1536 hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
1537 (wchar_t*)pdn + pdn->wDeviceOffset,
1538 (wchar_t*)pdn + pdn->wOutputOffset,
1540 GlobalUnlock (hDevNames);
1541 GlobalUnlock (hDevMode);
1545 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1546 g_set_error_literal (&priv->error,
1548 GTK_PRINT_ERROR_INTERNAL_ERROR,
1549 _("Invalid argument to CreateDC"));
1553 priv->print_context = _gtk_print_context_new (op);
1554 page_setup = create_page_setup (op);
1555 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1556 g_object_unref (page_setup);
1560 op_win32->surface = cairo_win32_printing_surface_create (hDC);
1561 dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
1562 dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
1564 cr = cairo_create (op_win32->surface);
1565 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1568 memset (&docinfo, 0, sizeof (DOCINFOW));
1569 docinfo.cbSize = sizeof (DOCINFOW);
1570 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1571 docinfo.lpszOutput = NULL;
1572 docinfo.lpszDatatype = NULL;
1575 job_id = StartDocW (hDC, &docinfo);
1576 g_free ((void *)docinfo.lpszDocName);
1579 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1580 g_set_error_literal (&priv->error,
1582 GTK_PRINT_ERROR_GENERAL,
1583 _("Error from StartDoc"));
1585 cairo_surface_destroy (op_win32->surface);
1586 op_win32->surface = NULL;
1590 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1591 op_win32->hdc = hDC;
1592 op_win32->devmode = hDevMode;
1593 op_win32->devnames = hDevNames;
1594 op_win32->job_id = job_id;
1595 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1596 op->priv->num_page_ranges = 0;
1597 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1598 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1599 &op->priv->num_page_ranges);
1600 op->priv->manual_num_copies = 1;
1601 op->priv->manual_collation = FALSE;
1602 op->priv->manual_reverse = FALSE;
1603 op->priv->manual_orientation = FALSE;
1604 op->priv->manual_scale = 1.0;
1605 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1606 op->priv->manual_number_up = 1;
1607 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1609 op->priv->start_page = win32_start_page;
1610 op->priv->end_page = win32_end_page;
1611 op->priv->end_run = win32_end_run;
1614 if (!*do_print && hDC != NULL)
1617 if (!*do_print && hDevMode != NULL)
1618 GlobalFree (hDevMode);
1620 if (!*do_print && hDevNames != NULL)
1621 GlobalFree (hDevNames);
1626 GtkPrintOperationResult
1627 gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
1632 LPPRINTDLGEXW printdlgex = NULL;
1633 LPPRINTPAGERANGE page_ranges = NULL;
1635 GtkWidget *invisible = NULL;
1636 GtkPrintOperationResult result;
1637 GtkPrintOperationWin32 *op_win32;
1638 GtkPrintOperationPrivate *priv;
1639 IPrintDialogCallback *callback;
1640 HPROPSHEETPAGE prop_page;
1646 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1647 priv->platform_data = op_win32;
1648 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1652 invisible = gtk_invisible_new ();
1653 parentHWnd = get_parent_hwnd (invisible);
1656 parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
1658 printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
1661 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1662 g_set_error_literal (&priv->error,
1664 GTK_PRINT_ERROR_NOMEM,
1665 _("Not enough free memory"));
1669 printdlgex->lStructSize = sizeof (PRINTDLGEXW);
1670 printdlgex->hwndOwner = parentHWnd;
1671 printdlgex->hDevMode = NULL;
1672 printdlgex->hDevNames = NULL;
1673 printdlgex->hDC = NULL;
1674 printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
1675 if (op->priv->current_page == -1)
1676 printdlgex->Flags |= PD_NOCURRENTPAGE;
1677 printdlgex->Flags2 = 0;
1678 printdlgex->ExclusionFlags = 0;
1680 page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR,
1681 MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
1684 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1685 g_set_error_literal (&priv->error,
1687 GTK_PRINT_ERROR_NOMEM,
1688 _("Not enough free memory"));
1692 printdlgex->nPageRanges = 0;
1693 printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
1694 printdlgex->lpPageRanges = page_ranges;
1695 printdlgex->nMinPage = 1;
1696 if (op->priv->nr_of_pages != -1)
1697 printdlgex->nMaxPage = op->priv->nr_of_pages;
1699 printdlgex->nMaxPage = 10000;
1700 printdlgex->nCopies = 1;
1701 printdlgex->hInstance = 0;
1702 printdlgex->lpPrintTemplateName = NULL;
1703 printdlgex->lpCallback = NULL;
1705 g_signal_emit_by_name (op, "create-custom-widget",
1706 &op->priv->custom_widget);
1707 if (op->priv->custom_widget) {
1708 prop_page = create_application_page (op);
1709 printdlgex->nPropertyPages = 1;
1710 printdlgex->lphPropertyPages = &prop_page;
1712 printdlgex->nPropertyPages = 0;
1713 printdlgex->lphPropertyPages = NULL;
1716 printdlgex->nStartPage = START_PAGE_GENERAL;
1717 printdlgex->dwResultAction = 0;
1719 dialog_from_print_settings (op, printdlgex);
1721 callback = print_callback_new ();
1722 printdlgex->lpCallback = (IUnknown *)callback;
1723 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1725 hResult = PrintDlgExW (printdlgex);
1726 IUnknown_Release ((IUnknown *)callback);
1727 gdk_win32_set_modal_dialog_libgtk_only (NULL);
1729 if (hResult != S_OK)
1731 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1732 if (hResult == E_OUTOFMEMORY)
1733 g_set_error_literal (&priv->error,
1735 GTK_PRINT_ERROR_NOMEM,
1736 _("Not enough free memory"));
1737 else if (hResult == E_INVALIDARG)
1738 g_set_error_literal (&priv->error,
1740 GTK_PRINT_ERROR_INTERNAL_ERROR,
1741 _("Invalid argument to PrintDlgEx"));
1742 else if (hResult == E_POINTER)
1743 g_set_error_literal (&priv->error,
1745 GTK_PRINT_ERROR_INTERNAL_ERROR,
1746 _("Invalid pointer to PrintDlgEx"));
1747 else if (hResult == E_HANDLE)
1748 g_set_error_literal (&priv->error,
1750 GTK_PRINT_ERROR_INTERNAL_ERROR,
1751 _("Invalid handle to PrintDlgEx"));
1753 g_set_error_literal (&priv->error,
1755 GTK_PRINT_ERROR_GENERAL,
1756 _("Unspecified error"));
1760 if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
1761 printdlgex->dwResultAction == PD_RESULT_APPLY)
1763 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1764 dialog_to_print_settings (op, printdlgex);
1767 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
1769 if (printdlgex->dwResultAction == PD_RESULT_PRINT)
1773 double dpi_x, dpi_y;
1775 GtkPageSetup *page_setup;
1777 priv->print_context = _gtk_print_context_new (op);
1778 page_setup = create_page_setup (op);
1779 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1780 g_object_unref (page_setup);
1784 op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
1786 dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
1787 dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
1789 cr = cairo_create (op_win32->surface);
1790 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1793 memset ( &docinfo, 0, sizeof (DOCINFOW));
1794 docinfo.cbSize = sizeof (DOCINFOW);
1795 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1796 docinfo.lpszOutput = (LPCWSTR) NULL;
1797 docinfo.lpszDatatype = (LPCWSTR) NULL;
1800 job_id = StartDocW (printdlgex->hDC, &docinfo);
1801 g_free ((void *)docinfo.lpszDocName);
1804 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1805 g_set_error_literal (&priv->error,
1807 GTK_PRINT_ERROR_GENERAL,
1808 _("Error from StartDoc"));
1810 cairo_surface_destroy (op_win32->surface);
1811 op_win32->surface = NULL;
1815 op_win32->hdc = printdlgex->hDC;
1816 op_win32->devmode = printdlgex->hDevMode;
1817 op_win32->devnames = printdlgex->hDevNames;
1818 op_win32->job_id = job_id;
1820 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1821 op->priv->num_page_ranges = 0;
1822 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1823 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1824 &op->priv->num_page_ranges);
1825 op->priv->manual_num_copies = printdlgex->nCopies;
1826 op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
1827 op->priv->manual_reverse = FALSE;
1828 op->priv->manual_orientation = FALSE;
1829 op->priv->manual_scale = 1.0;
1830 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1831 op->priv->manual_number_up = 1;
1832 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1835 op->priv->start_page = win32_start_page;
1836 op->priv->end_page = win32_end_page;
1837 op->priv->end_run = win32_end_run;
1840 if (!*do_print && printdlgex && printdlgex->hDC != NULL)
1841 DeleteDC (printdlgex->hDC);
1843 if (!*do_print && printdlgex && printdlgex->hDevMode != NULL)
1844 GlobalFree (printdlgex->hDevMode);
1846 if (!*do_print && printdlgex && printdlgex->hDevNames != NULL)
1847 GlobalFree (printdlgex->hDevNames);
1850 GlobalFree (page_ranges);
1853 GlobalFree (printdlgex);
1856 gtk_widget_destroy (invisible);
1861 GtkPrintOperationResult
1862 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
1863 gboolean show_dialog,
1868 return gtk_print_operation_run_with_dialog (op, parent, do_print);
1870 return gtk_print_operation_run_without_dialog (op, do_print);
1874 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
1875 cairo_surface_t *surface,
1877 const gchar *filename)
1880 HENHMETAFILE metafile;
1882 dc = cairo_win32_surface_get_dc (surface);
1883 cairo_surface_destroy (surface);
1884 metafile = CloseEnhMetaFile (dc);
1885 DeleteEnhMetaFile (metafile);
1887 ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
1891 _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
1892 cairo_surface_t *surface,
1895 HDC dc = cairo_win32_surface_get_dc (surface);
1900 _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
1901 cairo_surface_t *surface,
1906 cairo_surface_show_page (surface);
1908 /* TODO: Enhanced metafiles don't support multiple pages.
1910 dc = cairo_win32_surface_get_dc (surface);
1915 _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
1916 GtkPageSetup *page_setup,
1921 GtkPaperSize *paper_size;
1926 gunichar2 *filename_utf16;
1929 template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
1930 fd = g_mkstemp (template);
1933 filename = g_strconcat (template, ".emf", NULL);
1936 filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1939 paper_size = gtk_page_setup_get_paper_size (page_setup);
1941 /* The rectangle dimensions are given in hundredths of a millimeter */
1943 rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
1945 rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
1947 metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
1948 &rect, L"Gtk+\0Print Preview\0\0");
1949 if (metafile_dc == NULL)
1951 g_warning ("Can't create metafile");
1955 *target = (char *)filename_utf16;
1957 *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
1958 *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
1960 return cairo_win32_printing_surface_create (metafile_dc);
1964 _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
1965 GtkPageSetup *page_setup,
1966 cairo_surface_t *surface)
1968 /* TODO: Implement */
1972 gtk_print_run_page_setup_dialog (GtkWindow *parent,
1973 GtkPageSetup *page_setup,
1974 GtkPrintSettings *settings)
1976 LPPAGESETUPDLGW pagesetupdlg = NULL;
1978 gboolean free_settings;
1979 const char *printer;
1980 GtkPaperSize *paper_size;
1981 DWORD measure_system;
1985 pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
1989 free_settings = FALSE;
1990 if (settings == NULL)
1992 settings = gtk_print_settings_new ();
1993 free_settings = TRUE;
1996 memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
1998 pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
2001 pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
2003 pagesetupdlg->hwndOwner = NULL;
2005 pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
2006 pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup);
2007 pagesetupdlg->hDevNames = NULL;
2008 printer = gtk_print_settings_get_printer (settings);
2010 pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
2012 GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
2013 (LPWSTR)&measure_system, sizeof (DWORD));
2015 if (measure_system == 0)
2017 pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2023 pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
2024 unit = GTK_UNIT_INCH;
2028 /* This is the object we return, we allocate it here so that
2029 * we can use the default page margins */
2031 page_setup = gtk_page_setup_copy (page_setup);
2033 page_setup = gtk_page_setup_new ();
2035 pagesetupdlg->Flags |= PSD_MARGINS;
2036 pagesetupdlg->rtMargin.left =
2037 floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
2038 pagesetupdlg->rtMargin.right =
2039 floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
2040 pagesetupdlg->rtMargin.top =
2041 floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
2042 pagesetupdlg->rtMargin.bottom =
2043 floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
2045 pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
2046 pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
2047 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
2049 res = PageSetupDlgW (pagesetupdlg);
2050 gdk_win32_set_modal_dialog_libgtk_only (NULL);
2054 if (pagesetupdlg->hDevNames != NULL)
2055 devnames_to_settings (settings, pagesetupdlg->hDevNames);
2057 if (pagesetupdlg->hDevMode != NULL)
2058 devmode_to_settings (settings, pagesetupdlg->hDevMode);
2063 gtk_page_setup_set_orientation (page_setup,
2064 gtk_print_settings_get_orientation (settings));
2065 paper_size = gtk_print_settings_get_paper_size (settings);
2068 gtk_page_setup_set_paper_size (page_setup, paper_size);
2069 gtk_paper_size_free (paper_size);
2072 if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2079 unit = GTK_UNIT_INCH;
2083 gtk_page_setup_set_left_margin (page_setup,
2084 pagesetupdlg->rtMargin.left / scale,
2086 gtk_page_setup_set_right_margin (page_setup,
2087 pagesetupdlg->rtMargin.right / scale,
2089 gtk_page_setup_set_top_margin (page_setup,
2090 pagesetupdlg->rtMargin.top / scale,
2092 gtk_page_setup_set_bottom_margin (page_setup,
2093 pagesetupdlg->rtMargin.bottom / scale,
2098 g_object_unref (settings);
2104 gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
2105 GtkPageSetup *page_setup,
2106 GtkPrintSettings *settings,
2107 GtkPageSetupDoneFunc done_cb,
2110 GtkPageSetup *new_page_setup;
2112 new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
2113 done_cb (new_page_setup, data);
2114 g_object_unref (new_page_setup);
2117 #define __GTK_PRINT_OPERATION_WIN32_C__
2118 #include "gtkaliasdef.c"