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, see <http://www.gnu.org/licenses/>.
20 #define _WIN32_WINNT 0x0500
21 #define WINVER _WIN32_WINNT
34 #include <cairo-win32.h>
36 #include "gtkprintoperation-private.h"
37 #include "gtkprint-win32.h"
39 #include "gtkinvisible.h"
43 #include "gtkwin32embedwidget.h"
45 #define MAX_PAGE_RANGES 20
46 #define STATUS_POLLING_TIME 2000
48 #ifndef JOB_STATUS_RESTART
49 #define JOB_STATUS_RESTART 0x800
52 #ifndef JOB_STATUS_COMPLETE
53 #define JOB_STATUS_COMPLETE 0x1000
64 cairo_surface_t *surface;
65 GtkWidget *embed_widget;
66 } GtkPrintOperationWin32;
68 static void win32_poll_status (GtkPrintOperation *op);
70 static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}};
72 #if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK)
74 #define INTERFACE IPrintDialogCallback
75 DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown)
77 STDMETHOD (QueryInterface)(THIS_ REFIID,LPVOID*) PURE;
78 STDMETHOD_ (ULONG, AddRef)(THIS) PURE;
79 STDMETHOD_ (ULONG, Release)(THIS) PURE;
80 STDMETHOD (InitDone)(THIS) PURE;
81 STDMETHOD (SelectionChange)(THIS) PURE;
82 STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE;
86 static UINT got_gdk_events_message;
89 run_mainloop_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
91 if (uiMsg == WM_INITDIALOG)
93 gdk_win32_set_modal_dialog_libgtk_only (hdlg);
94 while (gtk_events_pending ())
95 gtk_main_iteration ();
97 else if (uiMsg == got_gdk_events_message)
99 while (gtk_events_pending ())
100 gtk_main_iteration ();
106 static GtkPageOrientation
107 orientation_from_win32 (short orientation)
109 if (orientation == DMORIENT_LANDSCAPE)
110 return GTK_PAGE_ORIENTATION_LANDSCAPE;
111 return GTK_PAGE_ORIENTATION_PORTRAIT;
115 orientation_to_win32 (GtkPageOrientation orientation)
117 if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
118 orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
119 return DMORIENT_LANDSCAPE;
120 return DMORIENT_PORTRAIT;
123 static GtkPaperSize *
124 paper_size_from_win32 (short size)
130 case DMPAPER_LETTER_TRANSVERSE:
132 case DMPAPER_LETTERSMALL:
135 case DMPAPER_TABLOID:
142 case DMPAPER_STATEMENT:
145 case DMPAPER_EXECUTIVE:
146 name = "na_executive";
149 case DMPAPER_A3_TRANSVERSE:
153 case DMPAPER_A4SMALL:
154 case DMPAPER_A4_TRANSVERSE:
158 case DMPAPER_A5_TRANSVERSE:
165 case DMPAPER_B5_TRANSVERSE:
181 name = "na_number-9";
184 name = "na_number-10";
187 name = "na_number-11";
190 name = "na_number-12";
193 name = "na_number-14";
219 case DMPAPER_ENV_C65:
231 case DMPAPER_ENV_ITALY:
234 case DMPAPER_ENV_MONARCH:
237 case DMPAPER_ENV_PERSONAL:
238 name = "na_personal";
240 case DMPAPER_FANFOLD_US:
241 name = "na_fanfold-us";
243 case DMPAPER_FANFOLD_STD_GERMAN:
244 name = "na_fanfold-eur";
246 case DMPAPER_FANFOLD_LGL_GERMAN:
247 name = "na_foolscap";
252 case DMPAPER_JAPANESE_POSTCARD:
261 case DMPAPER_ENV_INVITE:
264 case DMPAPER_LETTER_EXTRA:
265 case DMPAPER_LETTER_EXTRA_TRANSVERSE:
266 name = "na_letter-extra";
268 case DMPAPER_LEGAL_EXTRA:
269 name = "na_legal-extra";
271 case DMPAPER_TABLOID_EXTRA:
274 case DMPAPER_A4_EXTRA:
275 name = "iso_a4-extra";
280 case DMPAPER_LETTER_PLUS:
281 name = "na_letter-plus";
283 case DMPAPER_A3_EXTRA:
284 case DMPAPER_A3_EXTRA_TRANSVERSE:
285 name = "iso_a3-extra";
287 case DMPAPER_A5_EXTRA:
288 name = "iso_a5-extra";
290 case DMPAPER_B5_EXTRA:
291 name = "iso_b5-extra";
303 return gtk_paper_size_new (name);
309 paper_size_to_win32 (GtkPaperSize *paper_size)
313 if (gtk_paper_size_is_custom (paper_size))
316 format = gtk_paper_size_get_name (paper_size);
318 if (strcmp (format, "na_letter") == 0)
319 return DMPAPER_LETTER;
320 if (strcmp (format, "na_ledger") == 0)
321 return DMPAPER_LEDGER;
322 if (strcmp (format, "na_legal") == 0)
323 return DMPAPER_LEGAL;
324 if (strcmp (format, "na_invoice") == 0)
325 return DMPAPER_STATEMENT;
326 if (strcmp (format, "na_executive") == 0)
327 return DMPAPER_EXECUTIVE;
328 if (strcmp (format, "iso_a2") == 0)
330 if (strcmp (format, "iso_a3") == 0)
332 if (strcmp (format, "iso_a4") == 0)
334 if (strcmp (format, "iso_a5") == 0)
336 if (strcmp (format, "iso_b4") == 0)
338 if (strcmp (format, "iso_b5") == 0)
340 if (strcmp (format, "na_quarto") == 0)
341 return DMPAPER_QUARTO;
342 if (strcmp (format, "na_10x14") == 0)
343 return DMPAPER_10X14;
344 if (strcmp (format, "na_number-9") == 0)
345 return DMPAPER_ENV_9;
346 if (strcmp (format, "na_number-10") == 0)
347 return DMPAPER_ENV_10;
348 if (strcmp (format, "na_number-11") == 0)
349 return DMPAPER_ENV_11;
350 if (strcmp (format, "na_number-12") == 0)
351 return DMPAPER_ENV_12;
352 if (strcmp (format, "na_number-14") == 0)
353 return DMPAPER_ENV_14;
354 if (strcmp (format, "na_c") == 0)
355 return DMPAPER_CSHEET;
356 if (strcmp (format, "na_d") == 0)
357 return DMPAPER_DSHEET;
358 if (strcmp (format, "na_e") == 0)
359 return DMPAPER_ESHEET;
360 if (strcmp (format, "iso_dl") == 0)
361 return DMPAPER_ENV_DL;
362 if (strcmp (format, "iso_c3") == 0)
363 return DMPAPER_ENV_C3;
364 if (strcmp (format, "iso_c4") == 0)
365 return DMPAPER_ENV_C4;
366 if (strcmp (format, "iso_c5") == 0)
367 return DMPAPER_ENV_C5;
368 if (strcmp (format, "iso_c6") == 0)
369 return DMPAPER_ENV_C6;
370 if (strcmp (format, "iso_c5c6") == 0)
371 return DMPAPER_ENV_C65;
372 if (strcmp (format, "iso_b6") == 0)
373 return DMPAPER_ENV_B6;
374 if (strcmp (format, "om_italian") == 0)
375 return DMPAPER_ENV_ITALY;
376 if (strcmp (format, "na_monarch") == 0)
377 return DMPAPER_ENV_MONARCH;
378 if (strcmp (format, "na_personal") == 0)
379 return DMPAPER_ENV_PERSONAL;
380 if (strcmp (format, "na_fanfold-us") == 0)
381 return DMPAPER_FANFOLD_US;
382 if (strcmp (format, "na_fanfold-eur") == 0)
383 return DMPAPER_FANFOLD_STD_GERMAN;
384 if (strcmp (format, "na_foolscap") == 0)
385 return DMPAPER_FANFOLD_LGL_GERMAN;
386 if (strcmp (format, "jpn_hagaki") == 0)
387 return DMPAPER_JAPANESE_POSTCARD;
388 if (strcmp (format, "na_9x11") == 0)
390 if (strcmp (format, "na_10x11") == 0)
391 return DMPAPER_10X11;
392 if (strcmp (format, "om_invite") == 0)
393 return DMPAPER_ENV_INVITE;
394 if (strcmp (format, "na_letter-extra") == 0)
395 return DMPAPER_LETTER_EXTRA;
396 if (strcmp (format, "na_legal-extra") == 0)
397 return DMPAPER_LEGAL_EXTRA;
398 if (strcmp (format, "na_arch") == 0)
399 return DMPAPER_TABLOID_EXTRA;
400 if (strcmp (format, "iso_a3-extra") == 0)
401 return DMPAPER_A3_EXTRA;
402 if (strcmp (format, "iso_a4-extra") == 0)
403 return DMPAPER_A4_EXTRA;
404 if (strcmp (format, "iso_a5-extra") == 0)
405 return DMPAPER_A5_EXTRA;
406 if (strcmp (format, "iso_b5-extra") == 0)
407 return DMPAPER_B5_EXTRA;
408 if (strcmp (format, "na_b-plus") == 0)
409 return DMPAPER_B_PLUS;
410 if (strcmp (format, "na_letter-plus") == 0)
411 return DMPAPER_LETTER_PLUS;
417 get_default_printer (void)
419 wchar_t *win32_printer_name = NULL;
420 gchar *printer_name = NULL;
423 GetDefaultPrinterW (NULL, &needed);
424 win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t));
425 if (!GetDefaultPrinterW (win32_printer_name, &needed))
427 g_free (win32_printer_name);
430 printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL);
431 g_free (win32_printer_name);
437 set_hard_margins (GtkPrintOperation *op)
439 double top, bottom, left, right;
440 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
442 top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
443 bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
444 - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
445 left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
446 right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
447 - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
449 _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
453 win32_start_page (GtkPrintOperation *op,
454 GtkPrintContext *print_context,
455 GtkPageSetup *page_setup)
457 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
459 GtkPaperSize *paper_size;
462 devmode = GlobalLock (op_win32->devmode);
464 devmode->dmFields |= DM_ORIENTATION;
465 devmode->dmOrientation =
466 orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
468 paper_size = gtk_page_setup_get_paper_size (page_setup);
469 devmode->dmFields |= DM_PAPERSIZE;
470 devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
471 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
472 if (devmode->dmPaperSize == 0)
474 devmode->dmPaperSize = DMPAPER_USER;
475 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
477 /* Lengths in DEVMODE are in tenths of a millimeter */
478 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
479 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
482 ResetDCW (op_win32->hdc, devmode);
484 GlobalUnlock (op_win32->devmode);
486 set_hard_margins (op);
487 x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
488 y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
489 cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
491 StartPage (op_win32->hdc);
495 win32_end_page (GtkPrintOperation *op,
496 GtkPrintContext *print_context)
498 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
500 cairo_surface_show_page (op_win32->surface);
502 EndPage (op_win32->hdc);
506 win32_poll_status_timeout (GtkPrintOperation *op)
508 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
510 op_win32->timeout_id = 0;
511 /* We need to ref this, as setting the status to finished
512 might unref the object */
514 win32_poll_status (op);
516 if (!gtk_print_operation_is_finished (op))
517 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
518 (GSourceFunc)win32_poll_status_timeout,
526 win32_end_run (GtkPrintOperation *op,
530 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
532 HANDLE printerHandle = 0;
534 cairo_surface_finish (op_win32->surface);
536 EndDoc (op_win32->hdc);
538 if (op->priv->track_print_status)
540 devnames = GlobalLock (op_win32->devnames);
541 if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
542 &printerHandle, NULL))
544 GlobalUnlock (op_win32->devnames);
547 GlobalFree (op_win32->devmode);
548 GlobalFree (op_win32->devnames);
550 cairo_surface_destroy (op_win32->surface);
551 op_win32->surface = NULL;
553 DeleteDC (op_win32->hdc);
555 if (printerHandle != 0)
557 op_win32->printerHandle = printerHandle;
558 win32_poll_status (op);
559 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
560 (GSourceFunc)win32_poll_status_timeout,
564 /* Dunno what happened, pretend its finished */
565 _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
569 win32_poll_status (GtkPrintOperation *op)
571 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
574 JOB_INFO_1W *job_info;
575 GtkPrintStatus status;
579 GetJobW (op_win32->printerHandle, op_win32->job_id,
580 1,(LPBYTE)NULL, 0, &needed);
581 data = g_malloc (needed);
582 ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
583 1, (LPBYTE)data, needed, &needed);
589 job_info = (JOB_INFO_1W *)data;
590 win32_status = job_info->Status;
592 if (job_info->pStatus)
593 status_str = g_utf16_to_utf8 (job_info->pStatus,
594 -1, NULL, NULL, NULL);
597 (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
598 status = GTK_PRINT_STATUS_FINISHED;
599 else if (win32_status &
600 (JOB_STATUS_OFFLINE |
601 JOB_STATUS_PAPEROUT |
603 JOB_STATUS_USER_INTERVENTION))
605 status = GTK_PRINT_STATUS_PENDING_ISSUE;
606 if (status_str == NULL)
608 if (win32_status & JOB_STATUS_OFFLINE)
609 status_str = g_strdup (_("Printer offline"));
610 else if (win32_status & JOB_STATUS_PAPEROUT)
611 status_str = g_strdup (_("Out of paper"));
612 else if (win32_status & JOB_STATUS_PAUSED)
613 status_str = g_strdup (_("Paused"));
614 else if (win32_status & JOB_STATUS_USER_INTERVENTION)
615 status_str = g_strdup (_("Need user intervention"));
618 else if (win32_status &
619 (JOB_STATUS_BLOCKED_DEVQ |
622 status = GTK_PRINT_STATUS_FINISHED_ABORTED;
623 else if (win32_status &
624 (JOB_STATUS_SPOOLING |
625 JOB_STATUS_DELETING))
626 status = GTK_PRINT_STATUS_PENDING;
627 else if (win32_status & JOB_STATUS_PRINTING)
628 status = GTK_PRINT_STATUS_PRINTING;
630 status = GTK_PRINT_STATUS_FINISHED;
633 status = GTK_PRINT_STATUS_FINISHED;
637 _gtk_print_operation_set_status (op, status, status_str);
643 op_win32_free (GtkPrintOperationWin32 *op_win32)
645 if (op_win32->printerHandle)
646 ClosePrinter (op_win32->printerHandle);
647 if (op_win32->timeout_id != 0)
648 g_source_remove (op_win32->timeout_id);
653 get_parent_hwnd (GtkWidget *widget)
655 gtk_widget_realize (widget);
656 return gdk_win32_window_get_handle (gtk_widget_get_window (widget));
660 devnames_to_settings (GtkPrintSettings *settings,
663 GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
664 gtk_print_settings_set_printer (settings, devnames->device);
665 gtk_print_win32_devnames_free (devnames);
669 devmode_to_settings (GtkPrintSettings *settings,
674 devmode = GlobalLock (hDevMode);
676 gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
677 devmode->dmDriverVersion);
678 if (devmode->dmDriverExtra != 0)
680 char *extra = g_base64_encode (((char *)devmode) + sizeof (DEVMODEW),
681 devmode->dmDriverExtra);
682 gtk_print_settings_set (settings,
683 GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
688 if (devmode->dmFields & DM_ORIENTATION)
689 gtk_print_settings_set_orientation (settings,
690 orientation_from_win32 (devmode->dmOrientation));
693 if (devmode->dmFields & DM_PAPERSIZE &&
694 devmode->dmPaperSize != 0)
696 GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
699 gtk_print_settings_set_paper_size (settings, paper_size);
700 gtk_paper_size_free (paper_size);
702 gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
704 else if ((devmode->dmFields & DM_PAPERSIZE &&
705 devmode->dmPaperSize == 0) ||
706 ((devmode->dmFields & DM_PAPERWIDTH) &&
707 (devmode->dmFields & DM_PAPERLENGTH)))
709 GtkPaperSize *paper_size;
710 char *form_name = NULL;
711 if (devmode->dmFields & DM_FORMNAME)
712 form_name = g_utf16_to_utf8 (devmode->dmFormName,
713 -1, NULL, NULL, NULL);
714 if (form_name == NULL || form_name[0] == 0)
715 form_name = g_strdup (_("Custom size"));
717 /* Lengths in DEVMODE are in tenths of a millimeter */
718 paper_size = gtk_paper_size_new_custom (form_name,
720 devmode->dmPaperWidth / 10.0,
721 devmode->dmPaperLength / 10.0,
723 gtk_print_settings_set_paper_size (settings, paper_size);
724 gtk_paper_size_free (paper_size);
727 if (devmode->dmFields & DM_SCALE)
728 gtk_print_settings_set_scale (settings, devmode->dmScale);
730 if (devmode->dmFields & DM_COPIES)
731 gtk_print_settings_set_n_copies (settings,
734 if (devmode->dmFields & DM_DEFAULTSOURCE)
737 switch (devmode->dmDefaultSource)
749 case DMBIN_ENVMANUAL:
750 source = "envelope-manual";
764 case DMBIN_FORMSOURCE:
765 source = "form-source";
767 case DMBIN_LARGECAPACITY:
768 source = "large-capacity";
771 source = "large-format";
777 source = "small-format";
780 gtk_print_settings_set_default_source (settings, source);
781 gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
784 if (devmode->dmFields & DM_PRINTQUALITY)
786 GtkPrintQuality quality;
787 switch (devmode->dmPrintQuality)
790 quality = GTK_PRINT_QUALITY_LOW;
793 quality = GTK_PRINT_QUALITY_NORMAL;
797 quality = GTK_PRINT_QUALITY_HIGH;
800 quality = GTK_PRINT_QUALITY_DRAFT;
803 gtk_print_settings_set_quality (settings, quality);
804 gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
807 if (devmode->dmFields & DM_COLOR)
808 gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
810 if (devmode->dmFields & DM_DUPLEX)
812 GtkPrintDuplex duplex;
813 switch (devmode->dmDuplex)
817 duplex = GTK_PRINT_DUPLEX_SIMPLEX;
819 case DMDUP_HORIZONTAL:
820 duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
823 duplex = GTK_PRINT_DUPLEX_VERTICAL;
827 gtk_print_settings_set_duplex (settings, duplex);
830 if (devmode->dmFields & DM_COLLATE)
831 gtk_print_settings_set_collate (settings,
832 devmode->dmCollate == DMCOLLATE_TRUE);
834 if (devmode->dmFields & DM_MEDIATYPE)
837 switch (devmode->dmMediaType)
840 case DMMEDIA_STANDARD:
841 media_type = "stationery";
843 case DMMEDIA_TRANSPARENCY:
844 media_type = "transparency";
847 media_type = "photographic-glossy";
850 gtk_print_settings_set_media_type (settings, media_type);
851 gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
854 if (devmode->dmFields & DM_DITHERTYPE)
857 switch (devmode->dmDitherType)
866 case DMDITHER_COARSE:
869 case DMDITHER_LINEART:
872 case DMDITHER_GRAYSCALE:
873 dither = "grayscale";
875 case DMDITHER_ERRORDIFFUSION:
876 dither = "error-diffusion";
879 gtk_print_settings_set_dither (settings, dither);
880 gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
883 GlobalUnlock (hDevMode);
887 dialog_to_print_settings (GtkPrintOperation *op,
888 LPPRINTDLGEXW printdlgex)
891 GtkPrintSettings *settings;
893 settings = gtk_print_settings_new ();
895 gtk_print_settings_set_print_pages (settings,
896 GTK_PRINT_PAGES_ALL);
897 if (printdlgex->Flags & PD_CURRENTPAGE)
898 gtk_print_settings_set_print_pages (settings,
899 GTK_PRINT_PAGES_CURRENT);
900 else if (printdlgex->Flags & PD_PAGENUMS)
901 gtk_print_settings_set_print_pages (settings,
902 GTK_PRINT_PAGES_RANGES);
904 if (printdlgex->nPageRanges > 0)
906 GtkPageRange *ranges;
907 ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
909 for (i = 0; i < printdlgex->nPageRanges; i++)
911 ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
912 ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
915 gtk_print_settings_set_page_ranges (settings, ranges,
916 printdlgex->nPageRanges);
920 if (printdlgex->hDevNames != NULL)
921 devnames_to_settings (settings, printdlgex->hDevNames);
923 if (printdlgex->hDevMode != NULL)
924 devmode_to_settings (settings, printdlgex->hDevMode);
926 gtk_print_operation_set_print_settings (op, settings);
930 devmode_from_settings (GtkPrintSettings *settings,
931 GtkPageSetup *page_setup)
936 GtkPaperSize *paper_size;
937 const char *extras_base64;
943 extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
945 extras = g_base64_decode (extras_base64, &extras_len);
947 hDevMode = GlobalAlloc (GMEM_MOVEABLE,
948 sizeof (DEVMODEW) + extras_len);
950 devmode = GlobalLock (hDevMode);
952 memset (devmode, 0, sizeof (DEVMODEW));
954 devmode->dmSpecVersion = DM_SPECVERSION;
955 devmode->dmSize = sizeof (DEVMODEW);
957 devmode->dmDriverExtra = 0;
958 if (extras && extras_len > 0)
960 devmode->dmDriverExtra = extras_len;
961 memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
964 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
965 devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
968 gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
970 GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
972 orientation = gtk_page_setup_get_orientation (page_setup);
973 devmode->dmFields |= DM_ORIENTATION;
974 devmode->dmOrientation = orientation_to_win32 (orientation);
978 paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
982 if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
983 (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
985 devmode->dmFields |= DM_PAPERSIZE;
986 devmode->dmPaperSize = size;
990 paper_size = gtk_print_settings_get_paper_size (settings);
994 devmode->dmFields |= DM_PAPERSIZE;
995 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
996 if (devmode->dmPaperSize == 0)
998 devmode->dmPaperSize = DMPAPER_USER;
999 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
1001 /* Lengths in DEVMODE are in tenths of a millimeter */
1002 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
1003 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
1005 gtk_paper_size_free (paper_size);
1008 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
1010 devmode->dmFields |= DM_SCALE;
1011 devmode->dmScale = gtk_print_settings_get_scale (settings);
1014 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
1016 devmode->dmFields |= DM_COPIES;
1017 devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
1020 if (gtk_print_settings_has_key (settings, "win32-default-source"))
1022 devmode->dmFields |= DM_DEFAULTSOURCE;
1023 devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
1025 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
1027 devmode->dmFields |= DM_DEFAULTSOURCE;
1028 devmode->dmDefaultSource = DMBIN_AUTO;
1030 val = gtk_print_settings_get_default_source (settings);
1031 if (strcmp (val, "auto") == 0)
1032 devmode->dmDefaultSource = DMBIN_AUTO;
1033 if (strcmp (val, "cassette") == 0)
1034 devmode->dmDefaultSource = DMBIN_CASSETTE;
1035 if (strcmp (val, "envelope") == 0)
1036 devmode->dmDefaultSource = DMBIN_ENVELOPE;
1037 if (strcmp (val, "envelope-manual") == 0)
1038 devmode->dmDefaultSource = DMBIN_ENVMANUAL;
1039 if (strcmp (val, "lower") == 0)
1040 devmode->dmDefaultSource = DMBIN_LOWER;
1041 if (strcmp (val, "manual") == 0)
1042 devmode->dmDefaultSource = DMBIN_MANUAL;
1043 if (strcmp (val, "middle") == 0)
1044 devmode->dmDefaultSource = DMBIN_MIDDLE;
1045 if (strcmp (val, "only-one") == 0)
1046 devmode->dmDefaultSource = DMBIN_ONLYONE;
1047 if (strcmp (val, "form-source") == 0)
1048 devmode->dmDefaultSource = DMBIN_FORMSOURCE;
1049 if (strcmp (val, "large-capacity") == 0)
1050 devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
1051 if (strcmp (val, "large-format") == 0)
1052 devmode->dmDefaultSource = DMBIN_LARGEFMT;
1053 if (strcmp (val, "tractor") == 0)
1054 devmode->dmDefaultSource = DMBIN_TRACTOR;
1055 if (strcmp (val, "small-format") == 0)
1056 devmode->dmDefaultSource = DMBIN_SMALLFMT;
1059 if (gtk_print_settings_has_key (settings, "win32-print-quality"))
1061 devmode->dmFields |= DM_PRINTQUALITY;
1062 devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
1064 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
1066 devmode->dmFields |= DM_PRINTQUALITY;
1067 devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
1069 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
1071 devmode->dmFields |= DM_PRINTQUALITY;
1072 switch (gtk_print_settings_get_quality (settings))
1074 case GTK_PRINT_QUALITY_LOW:
1075 devmode->dmPrintQuality = DMRES_LOW;
1077 case GTK_PRINT_QUALITY_DRAFT:
1078 devmode->dmPrintQuality = DMRES_DRAFT;
1081 case GTK_PRINT_QUALITY_NORMAL:
1082 devmode->dmPrintQuality = DMRES_MEDIUM;
1084 case GTK_PRINT_QUALITY_HIGH:
1085 devmode->dmPrintQuality = DMRES_HIGH;
1090 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
1092 devmode->dmFields |= DM_COLOR;
1093 if (gtk_print_settings_get_use_color (settings))
1094 devmode->dmColor = DMCOLOR_COLOR;
1096 devmode->dmColor = DMCOLOR_MONOCHROME;
1099 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
1101 devmode->dmFields |= DM_DUPLEX;
1102 switch (gtk_print_settings_get_duplex (settings))
1105 case GTK_PRINT_DUPLEX_SIMPLEX:
1106 devmode->dmDuplex = DMDUP_SIMPLEX;
1108 case GTK_PRINT_DUPLEX_HORIZONTAL:
1109 devmode->dmDuplex = DMDUP_HORIZONTAL;
1111 case GTK_PRINT_DUPLEX_VERTICAL:
1112 devmode->dmDuplex = DMDUP_VERTICAL;
1117 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
1119 devmode->dmFields |= DM_COLLATE;
1120 if (gtk_print_settings_get_collate (settings))
1121 devmode->dmCollate = DMCOLLATE_TRUE;
1123 devmode->dmCollate = DMCOLLATE_FALSE;
1126 if (gtk_print_settings_has_key (settings, "win32-media-type"))
1128 devmode->dmFields |= DM_MEDIATYPE;
1129 devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
1131 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
1133 devmode->dmFields |= DM_MEDIATYPE;
1134 devmode->dmMediaType = DMMEDIA_STANDARD;
1136 val = gtk_print_settings_get_media_type (settings);
1137 if (strcmp (val, "transparency") == 0)
1138 devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
1139 if (strcmp (val, "photographic-glossy") == 0)
1140 devmode->dmMediaType = DMMEDIA_GLOSSY;
1143 if (gtk_print_settings_has_key (settings, "win32-dither-type"))
1145 devmode->dmFields |= DM_DITHERTYPE;
1146 devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
1148 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
1150 devmode->dmFields |= DM_DITHERTYPE;
1151 devmode->dmDitherType = DMDITHER_FINE;
1153 val = gtk_print_settings_get_dither (settings);
1154 if (strcmp (val, "none") == 0)
1155 devmode->dmDitherType = DMDITHER_NONE;
1156 if (strcmp (val, "coarse") == 0)
1157 devmode->dmDitherType = DMDITHER_COARSE;
1158 if (strcmp (val, "fine") == 0)
1159 devmode->dmDitherType = DMDITHER_FINE;
1160 if (strcmp (val, "lineart") == 0)
1161 devmode->dmDitherType = DMDITHER_LINEART;
1162 if (strcmp (val, "grayscale") == 0)
1163 devmode->dmDitherType = DMDITHER_GRAYSCALE;
1164 if (strcmp (val, "error-diffusion") == 0)
1165 devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
1168 GlobalUnlock (hDevMode);
1174 dialog_from_print_settings (GtkPrintOperation *op,
1175 LPPRINTDLGEXW printdlgex)
1177 GtkPrintSettings *settings = op->priv->print_settings;
1178 const char *printer;
1180 if (settings == NULL)
1183 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
1185 GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
1187 switch (print_pages)
1190 case GTK_PRINT_PAGES_ALL:
1191 printdlgex->Flags |= PD_ALLPAGES;
1193 case GTK_PRINT_PAGES_CURRENT:
1194 printdlgex->Flags |= PD_CURRENTPAGE;
1196 case GTK_PRINT_PAGES_RANGES:
1197 printdlgex->Flags |= PD_PAGENUMS;
1201 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
1203 GtkPageRange *ranges;
1206 ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
1208 if (num_ranges > MAX_PAGE_RANGES)
1209 num_ranges = MAX_PAGE_RANGES;
1211 printdlgex->nPageRanges = num_ranges;
1212 for (i = 0; i < num_ranges; i++)
1214 printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
1215 printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
1219 printer = gtk_print_settings_get_printer (settings);
1221 printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1223 printdlgex->hDevMode = devmode_from_settings (settings,
1224 op->priv->default_page_setup);
1228 IPrintDialogCallback iPrintDialogCallback;
1231 } PrintDialogCallback;
1234 static ULONG STDMETHODCALLTYPE
1235 iprintdialogcallback_addref (IPrintDialogCallback *This)
1237 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1238 return ++callback->ref_count;
1241 static ULONG STDMETHODCALLTYPE
1242 iprintdialogcallback_release (IPrintDialogCallback *This)
1244 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1245 int ref_count = --callback->ref_count;
1253 static HRESULT STDMETHODCALLTYPE
1254 iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
1258 if (IsEqualIID (riid, &IID_IUnknown) ||
1259 IsEqualIID (riid, &myIID_IPrintDialogCallback))
1262 IUnknown_AddRef ((IUnknown *)This);
1268 return E_NOINTERFACE;
1272 static HRESULT STDMETHODCALLTYPE
1273 iprintdialogcallback_initdone (IPrintDialogCallback *This)
1278 static HRESULT STDMETHODCALLTYPE
1279 iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
1284 static HRESULT STDMETHODCALLTYPE
1285 iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
1292 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1294 if (!callback->set_hwnd)
1296 gdk_win32_set_modal_dialog_libgtk_only (hDlg);
1297 callback->set_hwnd = TRUE;
1298 while (gtk_events_pending ())
1299 gtk_main_iteration ();
1301 else if (uMsg == got_gdk_events_message)
1303 while (gtk_events_pending ())
1304 gtk_main_iteration ();
1313 static IPrintDialogCallbackVtbl ipdc_vtbl = {
1314 iprintdialogcallback_queryinterface,
1315 iprintdialogcallback_addref,
1316 iprintdialogcallback_release,
1317 iprintdialogcallback_initdone,
1318 iprintdialogcallback_selectionchange,
1319 iprintdialogcallback_handlemessage
1322 static IPrintDialogCallback *
1323 print_callback_new (void)
1325 PrintDialogCallback *callback;
1327 callback = g_new0 (PrintDialogCallback, 1);
1328 callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
1329 callback->ref_count = 1;
1330 callback->set_hwnd = FALSE;
1332 return &callback->iPrintDialogCallback;
1336 plug_grab_notify (GtkWidget *widget,
1337 gboolean was_grabbed,
1338 GtkPrintOperation *op)
1340 EnableWindow (GetAncestor (GDK_WINDOW_HWND (gtk_widget_get_window (widget)), GA_ROOT),
1345 static BOOL CALLBACK
1346 pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1348 GtkPrintOperation *op;
1349 GtkPrintOperationWin32 *op_win32;
1351 if (message == WM_INITDIALOG)
1353 PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
1356 op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
1357 op_win32 = op->priv->platform_data;
1359 SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
1361 plug = _gtk_win32_embed_widget_new (wnd);
1362 gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
1363 op_win32->embed_widget = plug;
1364 gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
1365 gtk_widget_show (op->priv->custom_widget);
1366 gtk_widget_show (plug);
1367 gdk_window_focus (gtk_widget_get_window (plug), GDK_CURRENT_TIME);
1369 /* This dialog is modal, so we grab the embed widget */
1370 gtk_grab_add (plug);
1372 /* When we lose the grab we need to disable the print dialog */
1373 g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
1376 else if (message == WM_DESTROY)
1378 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1379 op_win32 = op->priv->platform_data;
1381 g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
1382 gtk_widget_destroy (op_win32->embed_widget);
1383 op_win32->embed_widget = NULL;
1384 op->priv->custom_widget = NULL;
1388 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1389 op_win32 = op->priv->platform_data;
1391 return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
1392 wnd, message, wparam, lparam);
1398 static HPROPSHEETPAGE
1399 create_application_page (GtkPrintOperation *op)
1401 HPROPSHEETPAGE hpage;
1402 PROPSHEETPAGEW page;
1403 DLGTEMPLATE *template;
1406 WORD baseunitX, baseunitY;
1408 GtkRequisition requisition;
1409 const char *tab_label;
1411 /* Make the template the size of the custom widget size request */
1412 gtk_widget_get_preferred_size (op->priv->custom_widget,
1413 &requisition, NULL);
1415 base_units = GetDialogBaseUnits ();
1416 baseunitX = LOWORD (base_units);
1417 baseunitY = HIWORD (base_units);
1419 htemplate = GlobalAlloc (GMEM_MOVEABLE,
1420 sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
1421 template = GlobalLock (htemplate);
1422 template->style = WS_CHILDWINDOW | DS_CONTROL;
1423 template->dwExtendedStyle = WS_EX_CONTROLPARENT;
1425 template->x = MulDiv (0, 4, baseunitX);
1426 template->y = MulDiv (0, 8, baseunitY);
1427 template->cx = MulDiv (requisition.width, 4, baseunitX);
1428 template->cy = MulDiv (requisition.height, 8, baseunitY);
1430 array = (WORD *) (template+1);
1431 *array++ = 0; /* menu */
1432 *array++ = 0; /* class */
1433 *array++ = 0; /* title */
1435 memset (&page, 0, sizeof (page));
1436 page.dwSize = sizeof (page);
1437 page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
1438 page.hInstance = GetModuleHandle (NULL);
1439 page.pResource = template;
1441 tab_label = op->priv->custom_tab_label;
1442 if (tab_label == NULL)
1443 tab_label = g_get_application_name ();
1444 if (tab_label == NULL)
1445 tab_label = _("Application");
1446 page.pszTitle = g_utf8_to_utf16 (tab_label,
1447 -1, NULL, NULL, NULL);
1448 page.pfnDlgProc = pageDlgProc;
1449 page.pfnCallback = NULL;
1450 page.lParam = (LPARAM) op;
1451 hpage = CreatePropertySheetPageW (&page);
1453 GlobalUnlock (htemplate);
1455 /* TODO: We're leaking htemplate here... */
1460 static GtkPageSetup *
1461 create_page_setup (GtkPrintOperation *op)
1463 GtkPrintOperationPrivate *priv = op->priv;
1464 GtkPageSetup *page_setup;
1465 GtkPrintSettings *settings;
1467 if (priv->default_page_setup)
1468 page_setup = gtk_page_setup_copy (priv->default_page_setup);
1470 page_setup = gtk_page_setup_new ();
1472 settings = priv->print_settings;
1475 GtkPaperSize *paper_size;
1477 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1478 gtk_page_setup_set_orientation (page_setup,
1479 gtk_print_settings_get_orientation (settings));
1482 paper_size = gtk_print_settings_get_paper_size (settings);
1485 gtk_page_setup_set_paper_size (page_setup, paper_size);
1486 gtk_paper_size_free (paper_size);
1489 /* TODO: Margins? */
1495 GtkPrintOperationResult
1496 gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
1499 GtkPrintOperationResult result;
1500 GtkPrintOperationWin32 *op_win32;
1501 GtkPrintOperationPrivate *priv;
1502 GtkPrintSettings *settings;
1503 GtkPageSetup *page_setup;
1505 HGLOBAL hDevMode = NULL;
1506 HGLOBAL hDevNames = NULL;
1508 const char *printer = NULL;
1509 double dpi_x, dpi_y;
1518 settings = priv->print_settings;
1520 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1521 priv->platform_data = op_win32;
1522 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1523 printer = gtk_print_settings_get_printer (settings);
1527 /* No printer selected. Get the system default printer and store
1530 gchar *tmp_printer = get_default_printer ();
1533 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1534 g_set_error_literal (&priv->error,
1536 GTK_PRINT_ERROR_INTERNAL_ERROR,
1537 _("No printer found"));
1540 gtk_print_settings_set_printer (settings, tmp_printer);
1541 printer = gtk_print_settings_get_printer (settings);
1542 g_free (tmp_printer);
1545 hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1546 hDevMode = devmode_from_settings (settings, op->priv->default_page_setup);
1548 /* Create a printer DC for the print settings and page setup provided. */
1549 pdn = GlobalLock (hDevNames);
1550 pdm = GlobalLock (hDevMode);
1551 hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
1552 (wchar_t*)pdn + pdn->wDeviceOffset,
1553 (wchar_t*)pdn + pdn->wOutputOffset,
1555 GlobalUnlock (hDevNames);
1556 GlobalUnlock (hDevMode);
1560 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1561 g_set_error_literal (&priv->error,
1563 GTK_PRINT_ERROR_INTERNAL_ERROR,
1564 _("Invalid argument to CreateDC"));
1568 priv->print_context = _gtk_print_context_new (op);
1569 page_setup = create_page_setup (op);
1570 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1571 g_object_unref (page_setup);
1575 op_win32->surface = cairo_win32_printing_surface_create (hDC);
1576 dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
1577 dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
1579 cr = cairo_create (op_win32->surface);
1580 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1583 set_hard_margins (op);
1585 memset (&docinfo, 0, sizeof (DOCINFOW));
1586 docinfo.cbSize = sizeof (DOCINFOW);
1587 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1588 docinfo.lpszOutput = NULL;
1589 docinfo.lpszDatatype = NULL;
1592 job_id = StartDocW (hDC, &docinfo);
1593 g_free ((void *)docinfo.lpszDocName);
1596 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1597 g_set_error_literal (&priv->error,
1599 GTK_PRINT_ERROR_GENERAL,
1600 _("Error from StartDoc"));
1602 cairo_surface_destroy (op_win32->surface);
1603 op_win32->surface = NULL;
1607 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1608 op_win32->hdc = hDC;
1609 op_win32->devmode = hDevMode;
1610 op_win32->devnames = hDevNames;
1611 op_win32->job_id = job_id;
1612 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1613 op->priv->num_page_ranges = 0;
1614 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1615 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1616 &op->priv->num_page_ranges);
1617 op->priv->manual_num_copies = 1;
1618 op->priv->manual_collation = FALSE;
1619 op->priv->manual_reverse = FALSE;
1620 op->priv->manual_orientation = FALSE;
1621 op->priv->manual_scale = 1.0;
1622 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1623 op->priv->manual_number_up = 1;
1624 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1626 op->priv->start_page = win32_start_page;
1627 op->priv->end_page = win32_end_page;
1628 op->priv->end_run = win32_end_run;
1631 if (!*do_print && hDC != NULL)
1634 if (!*do_print && hDevMode != NULL)
1635 GlobalFree (hDevMode);
1637 if (!*do_print && hDevNames != NULL)
1638 GlobalFree (hDevNames);
1643 GtkPrintOperationResult
1644 gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
1649 LPPRINTDLGEXW printdlgex = NULL;
1650 LPPRINTPAGERANGE page_ranges = NULL;
1652 GtkWidget *invisible = NULL;
1653 GtkPrintOperationResult result;
1654 GtkPrintOperationWin32 *op_win32;
1655 GtkPrintOperationPrivate *priv;
1656 IPrintDialogCallback *callback;
1657 HPROPSHEETPAGE prop_page;
1663 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1664 priv->platform_data = op_win32;
1665 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1669 invisible = gtk_invisible_new ();
1670 parentHWnd = get_parent_hwnd (invisible);
1673 parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
1675 printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
1678 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1679 g_set_error_literal (&priv->error,
1681 GTK_PRINT_ERROR_NOMEM,
1682 _("Not enough free memory"));
1686 printdlgex->lStructSize = sizeof (PRINTDLGEXW);
1687 printdlgex->hwndOwner = parentHWnd;
1688 printdlgex->hDevMode = NULL;
1689 printdlgex->hDevNames = NULL;
1690 printdlgex->hDC = NULL;
1691 printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
1692 if (op->priv->current_page == -1)
1693 printdlgex->Flags |= PD_NOCURRENTPAGE;
1694 printdlgex->Flags2 = 0;
1695 printdlgex->ExclusionFlags = 0;
1697 page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR,
1698 MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
1701 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1702 g_set_error_literal (&priv->error,
1704 GTK_PRINT_ERROR_NOMEM,
1705 _("Not enough free memory"));
1709 printdlgex->nPageRanges = 0;
1710 printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
1711 printdlgex->lpPageRanges = page_ranges;
1712 printdlgex->nMinPage = 1;
1713 if (op->priv->nr_of_pages != -1)
1714 printdlgex->nMaxPage = op->priv->nr_of_pages;
1716 printdlgex->nMaxPage = 10000;
1717 printdlgex->nCopies = 1;
1718 printdlgex->hInstance = 0;
1719 printdlgex->lpPrintTemplateName = NULL;
1720 printdlgex->lpCallback = NULL;
1722 g_signal_emit_by_name (op, "create-custom-widget",
1723 &op->priv->custom_widget);
1724 if (op->priv->custom_widget) {
1725 prop_page = create_application_page (op);
1726 printdlgex->nPropertyPages = 1;
1727 printdlgex->lphPropertyPages = &prop_page;
1729 printdlgex->nPropertyPages = 0;
1730 printdlgex->lphPropertyPages = NULL;
1733 printdlgex->nStartPage = START_PAGE_GENERAL;
1734 printdlgex->dwResultAction = 0;
1736 dialog_from_print_settings (op, printdlgex);
1738 callback = print_callback_new ();
1739 printdlgex->lpCallback = (IUnknown *)callback;
1740 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1742 hResult = PrintDlgExW (printdlgex);
1743 IUnknown_Release ((IUnknown *)callback);
1744 gdk_win32_set_modal_dialog_libgtk_only (NULL);
1746 if (hResult != S_OK)
1748 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1749 if (hResult == E_OUTOFMEMORY)
1750 g_set_error_literal (&priv->error,
1752 GTK_PRINT_ERROR_NOMEM,
1753 _("Not enough free memory"));
1754 else if (hResult == E_INVALIDARG)
1755 g_set_error_literal (&priv->error,
1757 GTK_PRINT_ERROR_INTERNAL_ERROR,
1758 _("Invalid argument to PrintDlgEx"));
1759 else if (hResult == E_POINTER)
1760 g_set_error_literal (&priv->error,
1762 GTK_PRINT_ERROR_INTERNAL_ERROR,
1763 _("Invalid pointer to PrintDlgEx"));
1764 else if (hResult == E_HANDLE)
1765 g_set_error_literal (&priv->error,
1767 GTK_PRINT_ERROR_INTERNAL_ERROR,
1768 _("Invalid handle to PrintDlgEx"));
1770 g_set_error_literal (&priv->error,
1772 GTK_PRINT_ERROR_GENERAL,
1773 _("Unspecified error"));
1777 if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
1778 printdlgex->dwResultAction == PD_RESULT_APPLY)
1780 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1781 dialog_to_print_settings (op, printdlgex);
1784 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
1786 if (printdlgex->dwResultAction == PD_RESULT_PRINT)
1790 double dpi_x, dpi_y;
1792 GtkPageSetup *page_setup;
1794 priv->print_context = _gtk_print_context_new (op);
1795 page_setup = create_page_setup (op);
1796 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1797 g_object_unref (page_setup);
1801 op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
1803 dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
1804 dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
1806 cr = cairo_create (op_win32->surface);
1807 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1810 set_hard_margins (op);
1812 memset ( &docinfo, 0, sizeof (DOCINFOW));
1813 docinfo.cbSize = sizeof (DOCINFOW);
1814 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1815 docinfo.lpszOutput = (LPCWSTR) NULL;
1816 docinfo.lpszDatatype = (LPCWSTR) NULL;
1819 job_id = StartDocW (printdlgex->hDC, &docinfo);
1820 g_free ((void *)docinfo.lpszDocName);
1823 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1824 g_set_error_literal (&priv->error,
1826 GTK_PRINT_ERROR_GENERAL,
1827 _("Error from StartDoc"));
1829 cairo_surface_destroy (op_win32->surface);
1830 op_win32->surface = NULL;
1834 op_win32->hdc = printdlgex->hDC;
1835 op_win32->devmode = printdlgex->hDevMode;
1836 op_win32->devnames = printdlgex->hDevNames;
1837 op_win32->job_id = job_id;
1839 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1840 op->priv->num_page_ranges = 0;
1841 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1842 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1843 &op->priv->num_page_ranges);
1844 op->priv->manual_num_copies = printdlgex->nCopies;
1845 op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
1846 op->priv->manual_reverse = FALSE;
1847 op->priv->manual_orientation = FALSE;
1848 op->priv->manual_scale = 1.0;
1849 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1850 op->priv->manual_number_up = 1;
1851 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1854 op->priv->start_page = win32_start_page;
1855 op->priv->end_page = win32_end_page;
1856 op->priv->end_run = win32_end_run;
1859 if (!*do_print && printdlgex && printdlgex->hDC != NULL)
1860 DeleteDC (printdlgex->hDC);
1862 if (!*do_print && printdlgex && printdlgex->hDevMode != NULL)
1863 GlobalFree (printdlgex->hDevMode);
1865 if (!*do_print && printdlgex && printdlgex->hDevNames != NULL)
1866 GlobalFree (printdlgex->hDevNames);
1869 GlobalFree (page_ranges);
1872 GlobalFree (printdlgex);
1875 gtk_widget_destroy (invisible);
1880 GtkPrintOperationResult
1881 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
1882 gboolean show_dialog,
1887 return gtk_print_operation_run_with_dialog (op, parent, do_print);
1889 return gtk_print_operation_run_without_dialog (op, do_print);
1893 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
1894 cairo_surface_t *surface,
1896 const gchar *filename)
1899 HENHMETAFILE metafile;
1901 dc = cairo_win32_surface_get_dc (surface);
1902 cairo_surface_destroy (surface);
1903 metafile = CloseEnhMetaFile (dc);
1904 DeleteEnhMetaFile (metafile);
1906 ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
1910 _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
1911 cairo_surface_t *surface,
1914 HDC dc = cairo_win32_surface_get_dc (surface);
1919 _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
1920 cairo_surface_t *surface,
1925 cairo_surface_show_page (surface);
1927 /* TODO: Enhanced metafiles don't support multiple pages.
1929 dc = cairo_win32_surface_get_dc (surface);
1934 _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
1935 GtkPageSetup *page_setup,
1940 GtkPaperSize *paper_size;
1945 gunichar2 *filename_utf16;
1948 template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
1949 fd = g_mkstemp (template);
1952 filename = g_strconcat (template, ".emf", NULL);
1955 filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1958 paper_size = gtk_page_setup_get_paper_size (page_setup);
1960 /* The rectangle dimensions are given in hundredths of a millimeter */
1962 rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
1964 rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
1966 metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
1967 &rect, L"Gtk+\0Print Preview\0\0");
1968 if (metafile_dc == NULL)
1970 g_warning ("Can't create metafile");
1974 *target = (char *)filename_utf16;
1976 *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
1977 *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
1979 return cairo_win32_printing_surface_create (metafile_dc);
1983 _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
1984 GtkPageSetup *page_setup,
1985 cairo_surface_t *surface)
1987 /* TODO: Implement */
1991 gtk_print_run_page_setup_dialog (GtkWindow *parent,
1992 GtkPageSetup *page_setup,
1993 GtkPrintSettings *settings)
1995 LPPAGESETUPDLGW pagesetupdlg = NULL;
1997 gboolean free_settings;
1998 const char *printer;
1999 GtkPaperSize *paper_size;
2000 DWORD measure_system;
2004 pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
2008 free_settings = FALSE;
2009 if (settings == NULL)
2011 settings = gtk_print_settings_new ();
2012 free_settings = TRUE;
2015 memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
2017 pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
2020 pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
2022 pagesetupdlg->hwndOwner = NULL;
2024 pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
2025 pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup);
2026 pagesetupdlg->hDevNames = NULL;
2027 printer = gtk_print_settings_get_printer (settings);
2029 pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
2031 GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
2032 (LPWSTR)&measure_system, sizeof (DWORD));
2034 if (measure_system == 0)
2036 pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2042 pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
2043 unit = GTK_UNIT_INCH;
2047 /* This is the object we return, we allocate it here so that
2048 * we can use the default page margins */
2050 page_setup = gtk_page_setup_copy (page_setup);
2052 page_setup = gtk_page_setup_new ();
2054 pagesetupdlg->Flags |= PSD_MARGINS;
2055 pagesetupdlg->rtMargin.left =
2056 floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
2057 pagesetupdlg->rtMargin.right =
2058 floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
2059 pagesetupdlg->rtMargin.top =
2060 floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
2061 pagesetupdlg->rtMargin.bottom =
2062 floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
2064 pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
2065 pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
2066 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
2068 res = PageSetupDlgW (pagesetupdlg);
2069 gdk_win32_set_modal_dialog_libgtk_only (NULL);
2073 if (pagesetupdlg->hDevNames != NULL)
2074 devnames_to_settings (settings, pagesetupdlg->hDevNames);
2076 if (pagesetupdlg->hDevMode != NULL)
2077 devmode_to_settings (settings, pagesetupdlg->hDevMode);
2082 gtk_page_setup_set_orientation (page_setup,
2083 gtk_print_settings_get_orientation (settings));
2084 paper_size = gtk_print_settings_get_paper_size (settings);
2087 gtk_page_setup_set_paper_size (page_setup, paper_size);
2088 gtk_paper_size_free (paper_size);
2091 if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2098 unit = GTK_UNIT_INCH;
2102 gtk_page_setup_set_left_margin (page_setup,
2103 pagesetupdlg->rtMargin.left / scale,
2105 gtk_page_setup_set_right_margin (page_setup,
2106 pagesetupdlg->rtMargin.right / scale,
2108 gtk_page_setup_set_top_margin (page_setup,
2109 pagesetupdlg->rtMargin.top / scale,
2111 gtk_page_setup_set_bottom_margin (page_setup,
2112 pagesetupdlg->rtMargin.bottom / scale,
2117 g_object_unref (settings);
2123 gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
2124 GtkPageSetup *page_setup,
2125 GtkPrintSettings *settings,
2126 GtkPageSetupDoneFunc done_cb,
2129 GtkPageSetup *new_page_setup;
2131 new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
2132 done_cb (new_page_setup, data);
2133 g_object_unref (new_page_setup);