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 set_hard_margins (GtkPrintOperation *op)
442 double top, bottom, left, right;
443 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
445 top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
446 bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT)
447 - GetDeviceCaps (op_win32->hdc, VERTRES) - top;
448 left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
449 right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH)
450 - GetDeviceCaps (op_win32->hdc, HORZRES) - left;
452 _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right);
456 win32_start_page (GtkPrintOperation *op,
457 GtkPrintContext *print_context,
458 GtkPageSetup *page_setup)
460 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
462 GtkPaperSize *paper_size;
465 devmode = GlobalLock (op_win32->devmode);
467 devmode->dmFields |= DM_ORIENTATION;
468 devmode->dmOrientation =
469 orientation_to_win32 (gtk_page_setup_get_orientation (page_setup));
471 paper_size = gtk_page_setup_get_paper_size (page_setup);
472 devmode->dmFields |= DM_PAPERSIZE;
473 devmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
474 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
475 if (devmode->dmPaperSize == 0)
477 devmode->dmPaperSize = DMPAPER_USER;
478 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
480 /* Lengths in DEVMODE are in tenths of a millimeter */
481 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
482 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
485 ResetDCW (op_win32->hdc, devmode);
487 GlobalUnlock (op_win32->devmode);
489 set_hard_margins (op);
490 x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX);
491 y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY);
492 cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off);
494 StartPage (op_win32->hdc);
498 win32_end_page (GtkPrintOperation *op,
499 GtkPrintContext *print_context)
501 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
503 cairo_surface_show_page (op_win32->surface);
505 EndPage (op_win32->hdc);
509 win32_poll_status_timeout (GtkPrintOperation *op)
511 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
513 op_win32->timeout_id = 0;
514 /* We need to ref this, as setting the status to finished
515 might unref the object */
517 win32_poll_status (op);
519 if (!gtk_print_operation_is_finished (op))
520 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
521 (GSourceFunc)win32_poll_status_timeout,
529 win32_end_run (GtkPrintOperation *op,
533 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
535 HANDLE printerHandle = 0;
537 cairo_surface_finish (op_win32->surface);
539 EndDoc (op_win32->hdc);
541 if (op->priv->track_print_status)
543 devnames = GlobalLock (op_win32->devnames);
544 if (!OpenPrinterW (((gunichar2 *)devnames) + devnames->wDeviceOffset,
545 &printerHandle, NULL))
547 GlobalUnlock (op_win32->devnames);
550 GlobalFree (op_win32->devmode);
551 GlobalFree (op_win32->devnames);
553 cairo_surface_destroy (op_win32->surface);
554 op_win32->surface = NULL;
556 DeleteDC (op_win32->hdc);
558 if (printerHandle != 0)
560 op_win32->printerHandle = printerHandle;
561 win32_poll_status (op);
562 op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME,
563 (GSourceFunc)win32_poll_status_timeout,
567 /* Dunno what happened, pretend its finished */
568 _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
572 win32_poll_status (GtkPrintOperation *op)
574 GtkPrintOperationWin32 *op_win32 = op->priv->platform_data;
577 JOB_INFO_1W *job_info;
578 GtkPrintStatus status;
582 GetJobW (op_win32->printerHandle, op_win32->job_id,
583 1,(LPBYTE)NULL, 0, &needed);
584 data = g_malloc (needed);
585 ret = GetJobW (op_win32->printerHandle, op_win32->job_id,
586 1, (LPBYTE)data, needed, &needed);
592 job_info = (JOB_INFO_1W *)data;
593 win32_status = job_info->Status;
595 if (job_info->pStatus)
596 status_str = g_utf16_to_utf8 (job_info->pStatus,
597 -1, NULL, NULL, NULL);
600 (JOB_STATUS_COMPLETE | JOB_STATUS_PRINTED))
601 status = GTK_PRINT_STATUS_FINISHED;
602 else if (win32_status &
603 (JOB_STATUS_OFFLINE |
604 JOB_STATUS_PAPEROUT |
606 JOB_STATUS_USER_INTERVENTION))
608 status = GTK_PRINT_STATUS_PENDING_ISSUE;
609 if (status_str == NULL)
611 if (win32_status & JOB_STATUS_OFFLINE)
612 status_str = g_strdup (_("Printer offline"));
613 else if (win32_status & JOB_STATUS_PAPEROUT)
614 status_str = g_strdup (_("Out of paper"));
615 else if (win32_status & JOB_STATUS_PAUSED)
616 status_str = g_strdup (_("Paused"));
617 else if (win32_status & JOB_STATUS_USER_INTERVENTION)
618 status_str = g_strdup (_("Need user intervention"));
621 else if (win32_status &
622 (JOB_STATUS_BLOCKED_DEVQ |
625 status = GTK_PRINT_STATUS_FINISHED_ABORTED;
626 else if (win32_status &
627 (JOB_STATUS_SPOOLING |
628 JOB_STATUS_DELETING))
629 status = GTK_PRINT_STATUS_PENDING;
630 else if (win32_status & JOB_STATUS_PRINTING)
631 status = GTK_PRINT_STATUS_PRINTING;
633 status = GTK_PRINT_STATUS_FINISHED;
636 status = GTK_PRINT_STATUS_FINISHED;
640 _gtk_print_operation_set_status (op, status, status_str);
646 op_win32_free (GtkPrintOperationWin32 *op_win32)
648 if (op_win32->printerHandle)
649 ClosePrinter (op_win32->printerHandle);
650 if (op_win32->timeout_id != 0)
651 g_source_remove (op_win32->timeout_id);
656 get_parent_hwnd (GtkWidget *widget)
658 gtk_widget_realize (widget);
659 return gdk_win32_drawable_get_handle (widget->window);
663 devnames_to_settings (GtkPrintSettings *settings,
666 GtkPrintWin32Devnames *devnames = gtk_print_win32_devnames_from_win32 (hDevNames);
667 gtk_print_settings_set_printer (settings, devnames->device);
668 gtk_print_win32_devnames_free (devnames);
672 devmode_to_settings (GtkPrintSettings *settings,
677 devmode = GlobalLock (hDevMode);
679 gtk_print_settings_set_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION,
680 devmode->dmDriverVersion);
681 if (devmode->dmDriverExtra != 0)
683 char *extra = g_base64_encode (((char *)devmode) + sizeof (DEVMODEW),
684 devmode->dmDriverExtra);
685 gtk_print_settings_set (settings,
686 GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA,
691 if (devmode->dmFields & DM_ORIENTATION)
692 gtk_print_settings_set_orientation (settings,
693 orientation_from_win32 (devmode->dmOrientation));
696 if (devmode->dmFields & DM_PAPERSIZE &&
697 devmode->dmPaperSize != 0)
699 GtkPaperSize *paper_size = paper_size_from_win32 (devmode->dmPaperSize);
702 gtk_print_settings_set_paper_size (settings, paper_size);
703 gtk_paper_size_free (paper_size);
705 gtk_print_settings_set_int (settings, "win32-paper-size", (int)devmode->dmPaperSize);
707 else if ((devmode->dmFields & DM_PAPERSIZE &&
708 devmode->dmPaperSize == 0) ||
709 ((devmode->dmFields & DM_PAPERWIDTH) &&
710 (devmode->dmFields & DM_PAPERLENGTH)))
712 GtkPaperSize *paper_size;
713 char *form_name = NULL;
714 if (devmode->dmFields & DM_FORMNAME)
715 form_name = g_utf16_to_utf8 (devmode->dmFormName,
716 -1, NULL, NULL, NULL);
717 if (form_name == NULL || form_name[0] == 0)
718 form_name = g_strdup (_("Custom size"));
720 /* Lengths in DEVMODE are in tenths of a millimeter */
721 paper_size = gtk_paper_size_new_custom (form_name,
723 devmode->dmPaperWidth / 10.0,
724 devmode->dmPaperLength / 10.0,
726 gtk_print_settings_set_paper_size (settings, paper_size);
727 gtk_paper_size_free (paper_size);
730 if (devmode->dmFields & DM_SCALE)
731 gtk_print_settings_set_scale (settings, devmode->dmScale);
733 if (devmode->dmFields & DM_COPIES)
734 gtk_print_settings_set_n_copies (settings,
737 if (devmode->dmFields & DM_DEFAULTSOURCE)
740 switch (devmode->dmDefaultSource)
752 case DMBIN_ENVMANUAL:
753 source = "envelope-manual";
767 case DMBIN_FORMSOURCE:
768 source = "form-source";
770 case DMBIN_LARGECAPACITY:
771 source = "large-capacity";
774 source = "large-format";
780 source = "small-format";
783 gtk_print_settings_set_default_source (settings, source);
784 gtk_print_settings_set_int (settings, "win32-default-source", devmode->dmDefaultSource);
787 if (devmode->dmFields & DM_PRINTQUALITY)
789 GtkPrintQuality quality;
790 switch (devmode->dmPrintQuality)
793 quality = GTK_PRINT_QUALITY_LOW;
796 quality = GTK_PRINT_QUALITY_NORMAL;
800 quality = GTK_PRINT_QUALITY_HIGH;
803 quality = GTK_PRINT_QUALITY_DRAFT;
806 gtk_print_settings_set_quality (settings, quality);
807 gtk_print_settings_set_int (settings, "win32-print-quality", devmode->dmPrintQuality);
810 if (devmode->dmFields & DM_COLOR)
811 gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR);
813 if (devmode->dmFields & DM_DUPLEX)
815 GtkPrintDuplex duplex;
816 switch (devmode->dmDuplex)
820 duplex = GTK_PRINT_DUPLEX_SIMPLEX;
822 case DMDUP_HORIZONTAL:
823 duplex = GTK_PRINT_DUPLEX_HORIZONTAL;
826 duplex = GTK_PRINT_DUPLEX_VERTICAL;
830 gtk_print_settings_set_duplex (settings, duplex);
833 if (devmode->dmFields & DM_COLLATE)
834 gtk_print_settings_set_collate (settings,
835 devmode->dmCollate == DMCOLLATE_TRUE);
837 if (devmode->dmFields & DM_MEDIATYPE)
840 switch (devmode->dmMediaType)
843 case DMMEDIA_STANDARD:
844 media_type = "stationery";
846 case DMMEDIA_TRANSPARENCY:
847 media_type = "transparency";
850 media_type = "photographic-glossy";
853 gtk_print_settings_set_media_type (settings, media_type);
854 gtk_print_settings_set_int (settings, "win32-media-type", devmode->dmMediaType);
857 if (devmode->dmFields & DM_DITHERTYPE)
860 switch (devmode->dmDitherType)
869 case DMDITHER_COARSE:
872 case DMDITHER_LINEART:
875 case DMDITHER_GRAYSCALE:
876 dither = "grayscale";
878 case DMDITHER_ERRORDIFFUSION:
879 dither = "error-diffusion";
882 gtk_print_settings_set_dither (settings, dither);
883 gtk_print_settings_set_int (settings, "win32-dither-type", devmode->dmDitherType);
886 GlobalUnlock (hDevMode);
890 dialog_to_print_settings (GtkPrintOperation *op,
891 LPPRINTDLGEXW printdlgex)
894 GtkPrintSettings *settings;
896 settings = gtk_print_settings_new ();
898 gtk_print_settings_set_print_pages (settings,
899 GTK_PRINT_PAGES_ALL);
900 if (printdlgex->Flags & PD_CURRENTPAGE)
901 gtk_print_settings_set_print_pages (settings,
902 GTK_PRINT_PAGES_CURRENT);
903 else if (printdlgex->Flags & PD_PAGENUMS)
904 gtk_print_settings_set_print_pages (settings,
905 GTK_PRINT_PAGES_RANGES);
907 if (printdlgex->nPageRanges > 0)
909 GtkPageRange *ranges;
910 ranges = g_new (GtkPageRange, printdlgex->nPageRanges);
912 for (i = 0; i < printdlgex->nPageRanges; i++)
914 ranges[i].start = printdlgex->lpPageRanges[i].nFromPage - 1;
915 ranges[i].end = printdlgex->lpPageRanges[i].nToPage - 1;
918 gtk_print_settings_set_page_ranges (settings, ranges,
919 printdlgex->nPageRanges);
923 if (printdlgex->hDevNames != NULL)
924 devnames_to_settings (settings, printdlgex->hDevNames);
926 if (printdlgex->hDevMode != NULL)
927 devmode_to_settings (settings, printdlgex->hDevMode);
929 gtk_print_operation_set_print_settings (op, settings);
933 devmode_from_settings (GtkPrintSettings *settings,
934 GtkPageSetup *page_setup)
939 GtkPaperSize *paper_size;
940 const char *extras_base64;
946 extras_base64 = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_EXTRA);
948 extras = g_base64_decode (extras_base64, &extras_len);
950 hDevMode = GlobalAlloc (GMEM_MOVEABLE,
951 sizeof (DEVMODEW) + extras_len);
953 devmode = GlobalLock (hDevMode);
955 memset (devmode, 0, sizeof (DEVMODEW));
957 devmode->dmSpecVersion = DM_SPECVERSION;
958 devmode->dmSize = sizeof (DEVMODEW);
960 devmode->dmDriverExtra = 0;
961 if (extras && extras_len > 0)
963 devmode->dmDriverExtra = extras_len;
964 memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len);
967 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION))
968 devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION);
971 gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
973 GtkPageOrientation orientation = gtk_print_settings_get_orientation (settings);
975 orientation = gtk_page_setup_get_orientation (page_setup);
976 devmode->dmFields |= DM_ORIENTATION;
977 devmode->dmOrientation = orientation_to_win32 (orientation);
981 paper_size = gtk_paper_size_copy (gtk_page_setup_get_paper_size (page_setup));
985 if (gtk_print_settings_has_key (settings, "win32-paper-size") &&
986 (size = gtk_print_settings_get_int (settings, "win32-paper-size")) != 0)
988 devmode->dmFields |= DM_PAPERSIZE;
989 devmode->dmPaperSize = size;
993 paper_size = gtk_print_settings_get_paper_size (settings);
997 devmode->dmFields |= DM_PAPERSIZE;
998 devmode->dmPaperSize = paper_size_to_win32 (paper_size);
999 if (devmode->dmPaperSize == 0)
1001 devmode->dmPaperSize = DMPAPER_USER;
1002 devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH;
1004 /* Lengths in DEVMODE are in tenths of a millimeter */
1005 devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0;
1006 devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0;
1008 gtk_paper_size_free (paper_size);
1011 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE))
1013 devmode->dmFields |= DM_SCALE;
1014 devmode->dmScale = gtk_print_settings_get_scale (settings);
1017 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES))
1019 devmode->dmFields |= DM_COPIES;
1020 devmode->dmCopies = gtk_print_settings_get_n_copies (settings);
1023 if (gtk_print_settings_has_key (settings, "win32-default-source"))
1025 devmode->dmFields |= DM_DEFAULTSOURCE;
1026 devmode->dmDefaultSource = gtk_print_settings_get_int (settings, "win32-default-source");
1028 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE))
1030 devmode->dmFields |= DM_DEFAULTSOURCE;
1031 devmode->dmDefaultSource = DMBIN_AUTO;
1033 val = gtk_print_settings_get_default_source (settings);
1034 if (strcmp (val, "auto") == 0)
1035 devmode->dmDefaultSource = DMBIN_AUTO;
1036 if (strcmp (val, "cassette") == 0)
1037 devmode->dmDefaultSource = DMBIN_CASSETTE;
1038 if (strcmp (val, "envelope") == 0)
1039 devmode->dmDefaultSource = DMBIN_ENVELOPE;
1040 if (strcmp (val, "envelope-manual") == 0)
1041 devmode->dmDefaultSource = DMBIN_ENVMANUAL;
1042 if (strcmp (val, "lower") == 0)
1043 devmode->dmDefaultSource = DMBIN_LOWER;
1044 if (strcmp (val, "manual") == 0)
1045 devmode->dmDefaultSource = DMBIN_MANUAL;
1046 if (strcmp (val, "middle") == 0)
1047 devmode->dmDefaultSource = DMBIN_MIDDLE;
1048 if (strcmp (val, "only-one") == 0)
1049 devmode->dmDefaultSource = DMBIN_ONLYONE;
1050 if (strcmp (val, "form-source") == 0)
1051 devmode->dmDefaultSource = DMBIN_FORMSOURCE;
1052 if (strcmp (val, "large-capacity") == 0)
1053 devmode->dmDefaultSource = DMBIN_LARGECAPACITY;
1054 if (strcmp (val, "large-format") == 0)
1055 devmode->dmDefaultSource = DMBIN_LARGEFMT;
1056 if (strcmp (val, "tractor") == 0)
1057 devmode->dmDefaultSource = DMBIN_TRACTOR;
1058 if (strcmp (val, "small-format") == 0)
1059 devmode->dmDefaultSource = DMBIN_SMALLFMT;
1062 if (gtk_print_settings_has_key (settings, "win32-print-quality"))
1064 devmode->dmFields |= DM_PRINTQUALITY;
1065 devmode->dmPrintQuality = gtk_print_settings_get_int (settings, "win32-print-quality");
1067 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_RESOLUTION))
1069 devmode->dmFields |= DM_PRINTQUALITY;
1070 devmode->dmPrintQuality = gtk_print_settings_get_resolution (settings);
1072 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_QUALITY))
1074 devmode->dmFields |= DM_PRINTQUALITY;
1075 switch (gtk_print_settings_get_quality (settings))
1077 case GTK_PRINT_QUALITY_LOW:
1078 devmode->dmPrintQuality = DMRES_LOW;
1080 case GTK_PRINT_QUALITY_DRAFT:
1081 devmode->dmPrintQuality = DMRES_DRAFT;
1084 case GTK_PRINT_QUALITY_NORMAL:
1085 devmode->dmPrintQuality = DMRES_MEDIUM;
1087 case GTK_PRINT_QUALITY_HIGH:
1088 devmode->dmPrintQuality = DMRES_HIGH;
1093 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_USE_COLOR))
1095 devmode->dmFields |= DM_COLOR;
1096 if (gtk_print_settings_get_use_color (settings))
1097 devmode->dmColor = DMCOLOR_COLOR;
1099 devmode->dmColor = DMCOLOR_MONOCHROME;
1102 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DUPLEX))
1104 devmode->dmFields |= DM_DUPLEX;
1105 switch (gtk_print_settings_get_duplex (settings))
1108 case GTK_PRINT_DUPLEX_SIMPLEX:
1109 devmode->dmDuplex = DMDUP_SIMPLEX;
1111 case GTK_PRINT_DUPLEX_HORIZONTAL:
1112 devmode->dmDuplex = DMDUP_HORIZONTAL;
1114 case GTK_PRINT_DUPLEX_VERTICAL:
1115 devmode->dmDuplex = DMDUP_VERTICAL;
1120 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_COLLATE))
1122 devmode->dmFields |= DM_COLLATE;
1123 if (gtk_print_settings_get_collate (settings))
1124 devmode->dmCollate = DMCOLLATE_TRUE;
1126 devmode->dmCollate = DMCOLLATE_FALSE;
1129 if (gtk_print_settings_has_key (settings, "win32-media-type"))
1131 devmode->dmFields |= DM_MEDIATYPE;
1132 devmode->dmMediaType = gtk_print_settings_get_int (settings, "win32-media-type");
1134 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_MEDIA_TYPE))
1136 devmode->dmFields |= DM_MEDIATYPE;
1137 devmode->dmMediaType = DMMEDIA_STANDARD;
1139 val = gtk_print_settings_get_media_type (settings);
1140 if (strcmp (val, "transparency") == 0)
1141 devmode->dmMediaType = DMMEDIA_TRANSPARENCY;
1142 if (strcmp (val, "photographic-glossy") == 0)
1143 devmode->dmMediaType = DMMEDIA_GLOSSY;
1146 if (gtk_print_settings_has_key (settings, "win32-dither-type"))
1148 devmode->dmFields |= DM_DITHERTYPE;
1149 devmode->dmDitherType = gtk_print_settings_get_int (settings, "win32-dither-type");
1151 else if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_DITHER))
1153 devmode->dmFields |= DM_DITHERTYPE;
1154 devmode->dmDitherType = DMDITHER_FINE;
1156 val = gtk_print_settings_get_dither (settings);
1157 if (strcmp (val, "none") == 0)
1158 devmode->dmDitherType = DMDITHER_NONE;
1159 if (strcmp (val, "coarse") == 0)
1160 devmode->dmDitherType = DMDITHER_COARSE;
1161 if (strcmp (val, "fine") == 0)
1162 devmode->dmDitherType = DMDITHER_FINE;
1163 if (strcmp (val, "lineart") == 0)
1164 devmode->dmDitherType = DMDITHER_LINEART;
1165 if (strcmp (val, "grayscale") == 0)
1166 devmode->dmDitherType = DMDITHER_GRAYSCALE;
1167 if (strcmp (val, "error-diffusion") == 0)
1168 devmode->dmDitherType = DMDITHER_ERRORDIFFUSION;
1171 GlobalUnlock (hDevMode);
1177 dialog_from_print_settings (GtkPrintOperation *op,
1178 LPPRINTDLGEXW printdlgex)
1180 GtkPrintSettings *settings = op->priv->print_settings;
1181 const char *printer;
1183 if (settings == NULL)
1186 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PRINT_PAGES))
1188 GtkPrintPages print_pages = gtk_print_settings_get_print_pages (settings);
1190 switch (print_pages)
1193 case GTK_PRINT_PAGES_ALL:
1194 printdlgex->Flags |= PD_ALLPAGES;
1196 case GTK_PRINT_PAGES_CURRENT:
1197 printdlgex->Flags |= PD_CURRENTPAGE;
1199 case GTK_PRINT_PAGES_RANGES:
1200 printdlgex->Flags |= PD_PAGENUMS;
1204 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_PAGE_RANGES))
1206 GtkPageRange *ranges;
1209 ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
1211 if (num_ranges > MAX_PAGE_RANGES)
1212 num_ranges = MAX_PAGE_RANGES;
1214 printdlgex->nPageRanges = num_ranges;
1215 for (i = 0; i < num_ranges; i++)
1217 printdlgex->lpPageRanges[i].nFromPage = ranges[i].start + 1;
1218 printdlgex->lpPageRanges[i].nToPage = ranges[i].end + 1;
1222 printer = gtk_print_settings_get_printer (settings);
1224 printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1226 printdlgex->hDevMode = devmode_from_settings (settings,
1227 op->priv->default_page_setup);
1231 IPrintDialogCallback iPrintDialogCallback;
1234 } PrintDialogCallback;
1237 static ULONG STDMETHODCALLTYPE
1238 iprintdialogcallback_addref (IPrintDialogCallback *This)
1240 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1241 return ++callback->ref_count;
1244 static ULONG STDMETHODCALLTYPE
1245 iprintdialogcallback_release (IPrintDialogCallback *This)
1247 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1248 int ref_count = --callback->ref_count;
1256 static HRESULT STDMETHODCALLTYPE
1257 iprintdialogcallback_queryinterface (IPrintDialogCallback *This,
1261 if (IsEqualIID (riid, &IID_IUnknown) ||
1262 IsEqualIID (riid, &myIID_IPrintDialogCallback))
1265 IUnknown_AddRef ((IUnknown *)This);
1271 return E_NOINTERFACE;
1275 static HRESULT STDMETHODCALLTYPE
1276 iprintdialogcallback_initdone (IPrintDialogCallback *This)
1281 static HRESULT STDMETHODCALLTYPE
1282 iprintdialogcallback_selectionchange (IPrintDialogCallback *This)
1287 static HRESULT STDMETHODCALLTYPE
1288 iprintdialogcallback_handlemessage (IPrintDialogCallback *This,
1295 PrintDialogCallback *callback = (PrintDialogCallback *)This;
1297 if (!callback->set_hwnd)
1299 gdk_win32_set_modal_dialog_libgtk_only (hDlg);
1300 callback->set_hwnd = TRUE;
1301 while (gtk_events_pending ())
1302 gtk_main_iteration ();
1304 else if (uMsg == got_gdk_events_message)
1306 while (gtk_events_pending ())
1307 gtk_main_iteration ();
1316 static IPrintDialogCallbackVtbl ipdc_vtbl = {
1317 iprintdialogcallback_queryinterface,
1318 iprintdialogcallback_addref,
1319 iprintdialogcallback_release,
1320 iprintdialogcallback_initdone,
1321 iprintdialogcallback_selectionchange,
1322 iprintdialogcallback_handlemessage
1325 static IPrintDialogCallback *
1326 print_callback_new (void)
1328 PrintDialogCallback *callback;
1330 callback = g_new0 (PrintDialogCallback, 1);
1331 callback->iPrintDialogCallback.lpVtbl = &ipdc_vtbl;
1332 callback->ref_count = 1;
1333 callback->set_hwnd = FALSE;
1335 return &callback->iPrintDialogCallback;
1339 plug_grab_notify (GtkWidget *widget,
1340 gboolean was_grabbed,
1341 GtkPrintOperation *op)
1343 EnableWindow (GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
1348 static BOOL CALLBACK
1349 pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1351 GtkPrintOperation *op;
1352 GtkPrintOperationWin32 *op_win32;
1354 if (message == WM_INITDIALOG)
1356 PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
1359 op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
1360 op_win32 = op->priv->platform_data;
1362 SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op);
1364 plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
1365 gtk_window_set_modal (GTK_WINDOW (plug), TRUE);
1366 op_win32->embed_widget = plug;
1367 gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
1368 gtk_widget_show (op->priv->custom_widget);
1369 gtk_widget_show (plug);
1370 gdk_window_focus (plug->window, GDK_CURRENT_TIME);
1372 /* This dialog is modal, so we grab the embed widget */
1373 gtk_grab_add (plug);
1375 /* When we lose the grab we need to disable the print dialog */
1376 g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
1379 else if (message == WM_DESTROY)
1381 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1382 op_win32 = op->priv->platform_data;
1384 g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
1385 gtk_widget_destroy (op_win32->embed_widget);
1386 op_win32->embed_widget = NULL;
1387 op->priv->custom_widget = NULL;
1391 op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
1392 op_win32 = op->priv->platform_data;
1394 return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
1395 wnd, message, wparam, lparam);
1401 static HPROPSHEETPAGE
1402 create_application_page (GtkPrintOperation *op)
1404 HPROPSHEETPAGE hpage;
1405 PROPSHEETPAGEW page;
1406 DLGTEMPLATE *template;
1409 WORD baseunitX, baseunitY;
1411 GtkRequisition requisition;
1412 const char *tab_label;
1414 /* Make the template the size of the custom widget size request */
1415 gtk_widget_size_request (op->priv->custom_widget, &requisition);
1417 base_units = GetDialogBaseUnits ();
1418 baseunitX = LOWORD (base_units);
1419 baseunitY = HIWORD (base_units);
1421 htemplate = GlobalAlloc (GMEM_MOVEABLE,
1422 sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
1423 template = GlobalLock (htemplate);
1424 template->style = WS_CHILDWINDOW | DS_CONTROL;
1425 template->dwExtendedStyle = WS_EX_CONTROLPARENT;
1427 template->x = MulDiv (0, 4, baseunitX);
1428 template->y = MulDiv (0, 8, baseunitY);
1429 template->cx = MulDiv (requisition.width, 4, baseunitX);
1430 template->cy = MulDiv (requisition.height, 8, baseunitY);
1432 array = (WORD *) (template+1);
1433 *array++ = 0; /* menu */
1434 *array++ = 0; /* class */
1435 *array++ = 0; /* title */
1437 memset (&page, 0, sizeof (page));
1438 page.dwSize = sizeof (page);
1439 page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
1440 page.hInstance = GetModuleHandle (NULL);
1441 page.pResource = template;
1443 tab_label = op->priv->custom_tab_label;
1444 if (tab_label == NULL)
1445 tab_label = g_get_application_name ();
1446 if (tab_label == NULL)
1447 tab_label = _("Application");
1448 page.pszTitle = g_utf8_to_utf16 (tab_label,
1449 -1, NULL, NULL, NULL);
1450 page.pfnDlgProc = pageDlgProc;
1451 page.pfnCallback = NULL;
1452 page.lParam = (LPARAM) op;
1453 hpage = CreatePropertySheetPageW (&page);
1455 GlobalUnlock (htemplate);
1457 /* TODO: We're leaking htemplate here... */
1462 static GtkPageSetup *
1463 create_page_setup (GtkPrintOperation *op)
1465 GtkPrintOperationPrivate *priv = op->priv;
1466 GtkPageSetup *page_setup;
1467 GtkPrintSettings *settings;
1469 if (priv->default_page_setup)
1470 page_setup = gtk_page_setup_copy (priv->default_page_setup);
1472 page_setup = gtk_page_setup_new ();
1474 settings = priv->print_settings;
1477 GtkPaperSize *paper_size;
1479 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1480 gtk_page_setup_set_orientation (page_setup,
1481 gtk_print_settings_get_orientation (settings));
1484 paper_size = gtk_print_settings_get_paper_size (settings);
1487 gtk_page_setup_set_paper_size (page_setup, paper_size);
1488 gtk_paper_size_free (paper_size);
1491 /* TODO: Margins? */
1497 GtkPrintOperationResult
1498 gtk_print_operation_run_without_dialog (GtkPrintOperation *op,
1501 GtkPrintOperationResult result;
1502 GtkPrintOperationWin32 *op_win32;
1503 GtkPrintOperationPrivate *priv;
1504 GtkPrintSettings *settings;
1505 GtkPageSetup *page_setup;
1507 HGLOBAL hDevMode = NULL;
1508 HGLOBAL hDevNames = NULL;
1510 const char *printer = NULL;
1511 double dpi_x, dpi_y;
1520 settings = priv->print_settings;
1522 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1523 priv->platform_data = op_win32;
1524 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1525 printer = gtk_print_settings_get_printer (settings);
1529 /* No printer selected. Get the system default printer and store
1532 gchar *tmp_printer = get_default_printer ();
1535 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1536 g_set_error_literal (&priv->error,
1538 GTK_PRINT_ERROR_INTERNAL_ERROR,
1539 _("No printer found"));
1542 gtk_print_settings_set_printer (settings, tmp_printer);
1543 printer = gtk_print_settings_get_printer (settings);
1544 g_free (tmp_printer);
1547 hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
1548 hDevMode = devmode_from_settings (settings, op->priv->default_page_setup);
1550 /* Create a printer DC for the print settings and page setup provided. */
1551 pdn = GlobalLock (hDevNames);
1552 pdm = GlobalLock (hDevMode);
1553 hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset,
1554 (wchar_t*)pdn + pdn->wDeviceOffset,
1555 (wchar_t*)pdn + pdn->wOutputOffset,
1557 GlobalUnlock (hDevNames);
1558 GlobalUnlock (hDevMode);
1562 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1563 g_set_error_literal (&priv->error,
1565 GTK_PRINT_ERROR_INTERNAL_ERROR,
1566 _("Invalid argument to CreateDC"));
1570 priv->print_context = _gtk_print_context_new (op);
1571 page_setup = create_page_setup (op);
1572 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1573 g_object_unref (page_setup);
1577 op_win32->surface = cairo_win32_printing_surface_create (hDC);
1578 dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX);
1579 dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY);
1581 cr = cairo_create (op_win32->surface);
1582 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1585 set_hard_margins (op);
1587 memset (&docinfo, 0, sizeof (DOCINFOW));
1588 docinfo.cbSize = sizeof (DOCINFOW);
1589 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1590 docinfo.lpszOutput = NULL;
1591 docinfo.lpszDatatype = NULL;
1594 job_id = StartDocW (hDC, &docinfo);
1595 g_free ((void *)docinfo.lpszDocName);
1598 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1599 g_set_error_literal (&priv->error,
1601 GTK_PRINT_ERROR_GENERAL,
1602 _("Error from StartDoc"));
1604 cairo_surface_destroy (op_win32->surface);
1605 op_win32->surface = NULL;
1609 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1610 op_win32->hdc = hDC;
1611 op_win32->devmode = hDevMode;
1612 op_win32->devnames = hDevNames;
1613 op_win32->job_id = job_id;
1614 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1615 op->priv->num_page_ranges = 0;
1616 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1617 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1618 &op->priv->num_page_ranges);
1619 op->priv->manual_num_copies = 1;
1620 op->priv->manual_collation = FALSE;
1621 op->priv->manual_reverse = FALSE;
1622 op->priv->manual_orientation = FALSE;
1623 op->priv->manual_scale = 1.0;
1624 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1625 op->priv->manual_number_up = 1;
1626 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1628 op->priv->start_page = win32_start_page;
1629 op->priv->end_page = win32_end_page;
1630 op->priv->end_run = win32_end_run;
1633 if (!*do_print && hDC != NULL)
1636 if (!*do_print && hDevMode != NULL)
1637 GlobalFree (hDevMode);
1639 if (!*do_print && hDevNames != NULL)
1640 GlobalFree (hDevNames);
1645 GtkPrintOperationResult
1646 gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
1651 LPPRINTDLGEXW printdlgex = NULL;
1652 LPPRINTPAGERANGE page_ranges = NULL;
1654 GtkWidget *invisible = NULL;
1655 GtkPrintOperationResult result;
1656 GtkPrintOperationWin32 *op_win32;
1657 GtkPrintOperationPrivate *priv;
1658 IPrintDialogCallback *callback;
1659 HPROPSHEETPAGE prop_page;
1665 op_win32 = g_new0 (GtkPrintOperationWin32, 1);
1666 priv->platform_data = op_win32;
1667 priv->free_platform_data = (GDestroyNotify) op_win32_free;
1671 invisible = gtk_invisible_new ();
1672 parentHWnd = get_parent_hwnd (invisible);
1675 parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
1677 printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
1680 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1681 g_set_error_literal (&priv->error,
1683 GTK_PRINT_ERROR_NOMEM,
1684 _("Not enough free memory"));
1688 printdlgex->lStructSize = sizeof (PRINTDLGEXW);
1689 printdlgex->hwndOwner = parentHWnd;
1690 printdlgex->hDevMode = NULL;
1691 printdlgex->hDevNames = NULL;
1692 printdlgex->hDC = NULL;
1693 printdlgex->Flags = PD_RETURNDC | PD_NOSELECTION;
1694 if (op->priv->current_page == -1)
1695 printdlgex->Flags |= PD_NOCURRENTPAGE;
1696 printdlgex->Flags2 = 0;
1697 printdlgex->ExclusionFlags = 0;
1699 page_ranges = (LPPRINTPAGERANGE) GlobalAlloc (GPTR,
1700 MAX_PAGE_RANGES * sizeof (PRINTPAGERANGE));
1703 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1704 g_set_error_literal (&priv->error,
1706 GTK_PRINT_ERROR_NOMEM,
1707 _("Not enough free memory"));
1711 printdlgex->nPageRanges = 0;
1712 printdlgex->nMaxPageRanges = MAX_PAGE_RANGES;
1713 printdlgex->lpPageRanges = page_ranges;
1714 printdlgex->nMinPage = 1;
1715 if (op->priv->nr_of_pages != -1)
1716 printdlgex->nMaxPage = op->priv->nr_of_pages;
1718 printdlgex->nMaxPage = 10000;
1719 printdlgex->nCopies = 1;
1720 printdlgex->hInstance = 0;
1721 printdlgex->lpPrintTemplateName = NULL;
1722 printdlgex->lpCallback = NULL;
1724 g_signal_emit_by_name (op, "create-custom-widget",
1725 &op->priv->custom_widget);
1726 if (op->priv->custom_widget) {
1727 prop_page = create_application_page (op);
1728 printdlgex->nPropertyPages = 1;
1729 printdlgex->lphPropertyPages = &prop_page;
1731 printdlgex->nPropertyPages = 0;
1732 printdlgex->lphPropertyPages = NULL;
1735 printdlgex->nStartPage = START_PAGE_GENERAL;
1736 printdlgex->dwResultAction = 0;
1738 dialog_from_print_settings (op, printdlgex);
1740 callback = print_callback_new ();
1741 printdlgex->lpCallback = (IUnknown *)callback;
1742 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
1744 hResult = PrintDlgExW (printdlgex);
1745 IUnknown_Release ((IUnknown *)callback);
1746 gdk_win32_set_modal_dialog_libgtk_only (NULL);
1748 if (hResult != S_OK)
1750 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1751 if (hResult == E_OUTOFMEMORY)
1752 g_set_error_literal (&priv->error,
1754 GTK_PRINT_ERROR_NOMEM,
1755 _("Not enough free memory"));
1756 else if (hResult == E_INVALIDARG)
1757 g_set_error_literal (&priv->error,
1759 GTK_PRINT_ERROR_INTERNAL_ERROR,
1760 _("Invalid argument to PrintDlgEx"));
1761 else if (hResult == E_POINTER)
1762 g_set_error_literal (&priv->error,
1764 GTK_PRINT_ERROR_INTERNAL_ERROR,
1765 _("Invalid pointer to PrintDlgEx"));
1766 else if (hResult == E_HANDLE)
1767 g_set_error_literal (&priv->error,
1769 GTK_PRINT_ERROR_INTERNAL_ERROR,
1770 _("Invalid handle to PrintDlgEx"));
1772 g_set_error_literal (&priv->error,
1774 GTK_PRINT_ERROR_GENERAL,
1775 _("Unspecified error"));
1779 if (printdlgex->dwResultAction == PD_RESULT_PRINT ||
1780 printdlgex->dwResultAction == PD_RESULT_APPLY)
1782 result = GTK_PRINT_OPERATION_RESULT_APPLY;
1783 dialog_to_print_settings (op, printdlgex);
1786 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
1788 if (printdlgex->dwResultAction == PD_RESULT_PRINT)
1792 double dpi_x, dpi_y;
1794 GtkPageSetup *page_setup;
1796 priv->print_context = _gtk_print_context_new (op);
1797 page_setup = create_page_setup (op);
1798 _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1799 g_object_unref (page_setup);
1803 op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC);
1805 dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
1806 dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
1808 cr = cairo_create (op_win32->surface);
1809 gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
1812 set_hard_margins (op);
1814 memset ( &docinfo, 0, sizeof (DOCINFOW));
1815 docinfo.cbSize = sizeof (DOCINFOW);
1816 docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL);
1817 docinfo.lpszOutput = (LPCWSTR) NULL;
1818 docinfo.lpszDatatype = (LPCWSTR) NULL;
1821 job_id = StartDocW (printdlgex->hDC, &docinfo);
1822 g_free ((void *)docinfo.lpszDocName);
1825 result = GTK_PRINT_OPERATION_RESULT_ERROR;
1826 g_set_error_literal (&priv->error,
1828 GTK_PRINT_ERROR_GENERAL,
1829 _("Error from StartDoc"));
1831 cairo_surface_destroy (op_win32->surface);
1832 op_win32->surface = NULL;
1836 op_win32->hdc = printdlgex->hDC;
1837 op_win32->devmode = printdlgex->hDevMode;
1838 op_win32->devnames = printdlgex->hDevNames;
1839 op_win32->job_id = job_id;
1841 op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings);
1842 op->priv->num_page_ranges = 0;
1843 if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES)
1844 op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings,
1845 &op->priv->num_page_ranges);
1846 op->priv->manual_num_copies = printdlgex->nCopies;
1847 op->priv->manual_collation = (printdlgex->Flags & PD_COLLATE) != 0;
1848 op->priv->manual_reverse = FALSE;
1849 op->priv->manual_orientation = FALSE;
1850 op->priv->manual_scale = 1.0;
1851 op->priv->manual_page_set = GTK_PAGE_SET_ALL;
1852 op->priv->manual_number_up = 1;
1853 op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
1856 op->priv->start_page = win32_start_page;
1857 op->priv->end_page = win32_end_page;
1858 op->priv->end_run = win32_end_run;
1861 if (!*do_print && printdlgex && printdlgex->hDC != NULL)
1862 DeleteDC (printdlgex->hDC);
1864 if (!*do_print && printdlgex && printdlgex->hDevMode != NULL)
1865 GlobalFree (printdlgex->hDevMode);
1867 if (!*do_print && printdlgex && printdlgex->hDevNames != NULL)
1868 GlobalFree (printdlgex->hDevNames);
1871 GlobalFree (page_ranges);
1874 GlobalFree (printdlgex);
1877 gtk_widget_destroy (invisible);
1882 GtkPrintOperationResult
1883 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
1884 gboolean show_dialog,
1889 return gtk_print_operation_run_with_dialog (op, parent, do_print);
1891 return gtk_print_operation_run_without_dialog (op, do_print);
1895 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
1896 cairo_surface_t *surface,
1898 const gchar *filename)
1901 HENHMETAFILE metafile;
1903 dc = cairo_win32_surface_get_dc (surface);
1904 cairo_surface_destroy (surface);
1905 metafile = CloseEnhMetaFile (dc);
1906 DeleteEnhMetaFile (metafile);
1908 ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
1912 _gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
1913 cairo_surface_t *surface,
1916 HDC dc = cairo_win32_surface_get_dc (surface);
1921 _gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
1922 cairo_surface_t *surface,
1927 cairo_surface_show_page (surface);
1929 /* TODO: Enhanced metafiles don't support multiple pages.
1931 dc = cairo_win32_surface_get_dc (surface);
1936 _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
1937 GtkPageSetup *page_setup,
1942 GtkPaperSize *paper_size;
1947 gunichar2 *filename_utf16;
1950 template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
1951 fd = g_mkstemp (template);
1954 filename = g_strconcat (template, ".emf", NULL);
1957 filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
1960 paper_size = gtk_page_setup_get_paper_size (page_setup);
1962 /* The rectangle dimensions are given in hundredths of a millimeter */
1964 rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
1966 rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
1968 metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
1969 &rect, L"Gtk+\0Print Preview\0\0");
1970 if (metafile_dc == NULL)
1972 g_warning ("Can't create metafile");
1976 *target = (char *)filename_utf16;
1978 *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
1979 *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
1981 return cairo_win32_printing_surface_create (metafile_dc);
1985 _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
1986 GtkPageSetup *page_setup,
1987 cairo_surface_t *surface)
1989 /* TODO: Implement */
1993 gtk_print_run_page_setup_dialog (GtkWindow *parent,
1994 GtkPageSetup *page_setup,
1995 GtkPrintSettings *settings)
1997 LPPAGESETUPDLGW pagesetupdlg = NULL;
1999 gboolean free_settings;
2000 const char *printer;
2001 GtkPaperSize *paper_size;
2002 DWORD measure_system;
2006 pagesetupdlg = (LPPAGESETUPDLGW)GlobalAlloc (GPTR, sizeof (PAGESETUPDLGW));
2010 free_settings = FALSE;
2011 if (settings == NULL)
2013 settings = gtk_print_settings_new ();
2014 free_settings = TRUE;
2017 memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW));
2019 pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW);
2022 pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent));
2024 pagesetupdlg->hwndOwner = NULL;
2026 pagesetupdlg->Flags = PSD_DEFAULTMINMARGINS;
2027 pagesetupdlg->hDevMode = devmode_from_settings (settings, page_setup);
2028 pagesetupdlg->hDevNames = NULL;
2029 printer = gtk_print_settings_get_printer (settings);
2031 pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer);
2033 GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER,
2034 (LPWSTR)&measure_system, sizeof (DWORD));
2036 if (measure_system == 0)
2038 pagesetupdlg->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2044 pagesetupdlg->Flags |= PSD_INTHOUSANDTHSOFINCHES;
2045 unit = GTK_UNIT_INCH;
2049 /* This is the object we return, we allocate it here so that
2050 * we can use the default page margins */
2052 page_setup = gtk_page_setup_copy (page_setup);
2054 page_setup = gtk_page_setup_new ();
2056 pagesetupdlg->Flags |= PSD_MARGINS;
2057 pagesetupdlg->rtMargin.left =
2058 floor (gtk_page_setup_get_left_margin (page_setup, unit) * scale + 0.5);
2059 pagesetupdlg->rtMargin.right =
2060 floor (gtk_page_setup_get_right_margin (page_setup, unit) * scale + 0.5);
2061 pagesetupdlg->rtMargin.top =
2062 floor (gtk_page_setup_get_top_margin (page_setup, unit) * scale + 0.5);
2063 pagesetupdlg->rtMargin.bottom =
2064 floor (gtk_page_setup_get_bottom_margin (page_setup, unit) * scale + 0.5);
2066 pagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK;
2067 pagesetupdlg->lpfnPageSetupHook = run_mainloop_hook;
2068 got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
2070 res = PageSetupDlgW (pagesetupdlg);
2071 gdk_win32_set_modal_dialog_libgtk_only (NULL);
2075 if (pagesetupdlg->hDevNames != NULL)
2076 devnames_to_settings (settings, pagesetupdlg->hDevNames);
2078 if (pagesetupdlg->hDevMode != NULL)
2079 devmode_to_settings (settings, pagesetupdlg->hDevMode);
2084 gtk_page_setup_set_orientation (page_setup,
2085 gtk_print_settings_get_orientation (settings));
2086 paper_size = gtk_print_settings_get_paper_size (settings);
2089 gtk_page_setup_set_paper_size (page_setup, paper_size);
2090 gtk_paper_size_free (paper_size);
2093 if (pagesetupdlg->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2100 unit = GTK_UNIT_INCH;
2104 gtk_page_setup_set_left_margin (page_setup,
2105 pagesetupdlg->rtMargin.left / scale,
2107 gtk_page_setup_set_right_margin (page_setup,
2108 pagesetupdlg->rtMargin.right / scale,
2110 gtk_page_setup_set_top_margin (page_setup,
2111 pagesetupdlg->rtMargin.top / scale,
2113 gtk_page_setup_set_bottom_margin (page_setup,
2114 pagesetupdlg->rtMargin.bottom / scale,
2119 g_object_unref (settings);
2125 gtk_print_run_page_setup_dialog_async (GtkWindow *parent,
2126 GtkPageSetup *page_setup,
2127 GtkPrintSettings *settings,
2128 GtkPageSetupDoneFunc done_cb,
2131 GtkPageSetup *new_page_setup;
2133 new_page_setup = gtk_print_run_page_setup_dialog (parent, page_setup, settings);
2134 done_cb (new_page_setup, data);
2135 g_object_unref (new_page_setup);
2138 #define __GTK_PRINT_OPERATION_WIN32_C__
2139 #include "gtkaliasdef.c"