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