X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkprintoperation-win32.c;h=04de8ebbeb178f44d8bd7d2db460199f96162a74;hb=ea043cab5718304d9b6170afa2d3f959fc99c718;hp=97e1aaa605785f09023393b1d3df2965adeb66bc;hpb=57a052b0b06704b2d91041c8ffe2c9ceb365acd7;p=~andy%2Fgtk diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c index 97e1aaa60..04de8ebbe 100644 --- a/gtk/gtkprintoperation-win32.c +++ b/gtk/gtkprintoperation-win32.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #ifndef _MSC_VER @@ -26,7 +24,13 @@ #define COBJMACROS #include "config.h" #include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include #include +#include #include #include #include "gtkprintoperation-private.h" @@ -35,7 +39,6 @@ #include "gtkinvisible.h" #include "gtkplug.h" #include "gtkstock.h" -#include "gtkalias.h" #include "gtk.h" #include "gtkwin32embedwidget.h" @@ -58,6 +61,7 @@ typedef struct { int job_id; guint timeout_id; + cairo_surface_t *surface; GtkWidget *embed_widget; } GtkPrintOperationWin32; @@ -65,6 +69,7 @@ static void win32_poll_status (GtkPrintOperation *op); static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}}; +#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK) #undef INTERFACE #define INTERFACE IPrintDialogCallback DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown) @@ -76,6 +81,7 @@ DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown) STDMETHOD (SelectionChange)(THIS) PURE; STDMETHOD (HandleMessage)(THIS_ HWND,UINT,WPARAM,LPARAM,LRESULT*) PURE; }; +#endif static UINT got_gdk_events_message; @@ -407,6 +413,42 @@ paper_size_to_win32 (GtkPaperSize *paper_size) return 0; } +static gchar* +get_default_printer (void) +{ + wchar_t *win32_printer_name = NULL; + gchar *printer_name = NULL; + DWORD needed; + + GetDefaultPrinterW (NULL, &needed); + win32_printer_name = g_malloc ((gsize) needed * sizeof (wchar_t)); + if (!GetDefaultPrinterW (win32_printer_name, &needed)) + { + g_free (win32_printer_name); + return NULL; + } + printer_name = g_utf16_to_utf8 (win32_printer_name, -1, NULL, NULL, NULL); + g_free (win32_printer_name); + + return printer_name; +} + +static void +set_hard_margins (GtkPrintOperation *op) +{ + double top, bottom, left, right; + GtkPrintOperationWin32 *op_win32 = op->priv->platform_data; + + top = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY); + bottom = GetDeviceCaps (op_win32->hdc, PHYSICALHEIGHT) + - GetDeviceCaps (op_win32->hdc, VERTRES) - top; + left = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX); + right = GetDeviceCaps (op_win32->hdc, PHYSICALWIDTH) + - GetDeviceCaps (op_win32->hdc, HORZRES) - left; + + _gtk_print_context_set_hard_margins (op->priv->print_context, top, bottom, left, right); +} + void win32_start_page (GtkPrintOperation *op, GtkPrintContext *print_context, @@ -415,6 +457,7 @@ win32_start_page (GtkPrintOperation *op, GtkPrintOperationWin32 *op_win32 = op->priv->platform_data; LPDEVMODEW devmode; GtkPaperSize *paper_size; + double x_off, y_off; devmode = GlobalLock (op_win32->devmode); @@ -430,6 +473,8 @@ win32_start_page (GtkPrintOperation *op, { devmode->dmPaperSize = DMPAPER_USER; devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH; + + /* Lengths in DEVMODE are in tenths of a millimeter */ devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0; devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0; } @@ -437,6 +482,11 @@ win32_start_page (GtkPrintOperation *op, ResetDCW (op_win32->hdc, devmode); GlobalUnlock (op_win32->devmode); + + set_hard_margins (op); + x_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETX); + y_off = GetDeviceCaps (op_win32->hdc, PHYSICALOFFSETY); + cairo_surface_set_device_offset (op_win32->surface, -x_off, -y_off); StartPage (op_win32->hdc); } @@ -446,6 +496,9 @@ win32_end_page (GtkPrintOperation *op, GtkPrintContext *print_context) { GtkPrintOperationWin32 *op_win32 = op->priv->platform_data; + + cairo_surface_show_page (op_win32->surface); + EndPage (op_win32->hdc); } @@ -461,7 +514,7 @@ win32_poll_status_timeout (GtkPrintOperation *op) win32_poll_status (op); if (!gtk_print_operation_is_finished (op)) - op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME, + op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME, (GSourceFunc)win32_poll_status_timeout, op); g_object_unref (op); @@ -477,6 +530,8 @@ win32_end_run (GtkPrintOperation *op, GtkPrintOperationWin32 *op_win32 = op->priv->platform_data; LPDEVNAMES devnames; HANDLE printerHandle = 0; + + cairo_surface_finish (op_win32->surface); EndDoc (op_win32->hdc); @@ -489,19 +544,19 @@ win32_end_run (GtkPrintOperation *op, GlobalUnlock (op_win32->devnames); } - GlobalFree(op_win32->devmode); - GlobalFree(op_win32->devnames); + GlobalFree (op_win32->devmode); + GlobalFree (op_win32->devnames); - cairo_surface_destroy (op->priv->surface); - op->priv->surface = NULL; + cairo_surface_destroy (op_win32->surface); + op_win32->surface = NULL; - DeleteDC(op_win32->hdc); + DeleteDC (op_win32->hdc); if (printerHandle != 0) { op_win32->printerHandle = printerHandle; win32_poll_status (op); - op_win32->timeout_id = g_timeout_add (STATUS_POLLING_TIME, + op_win32->timeout_id = gdk_threads_add_timeout (STATUS_POLLING_TIME, (GSourceFunc)win32_poll_status_timeout, op); } @@ -530,8 +585,9 @@ win32_poll_status (GtkPrintOperation *op) status_str = NULL; if (ret) { + DWORD win32_status; job_info = (JOB_INFO_1W *)data; - DWORD win32_status = job_info->Status; + win32_status = job_info->Status; if (job_info->pStatus) status_str = g_utf16_to_utf8 (job_info->pStatus, @@ -597,7 +653,7 @@ static HWND get_parent_hwnd (GtkWidget *widget) { gtk_widget_realize (widget); - return gdk_win32_drawable_get_handle (widget->window); + return gdk_win32_window_get_handle (gtk_widget_get_window (widget)); } static void @@ -657,18 +713,19 @@ devmode_to_settings (GtkPrintSettings *settings, -1, NULL, NULL, NULL); if (form_name == NULL || form_name[0] == 0) form_name = g_strdup (_("Custom size")); + + /* Lengths in DEVMODE are in tenths of a millimeter */ paper_size = gtk_paper_size_new_custom (form_name, form_name, - devmode->dmPaperWidth * 10.0, - devmode->dmPaperLength * 10.0, + devmode->dmPaperWidth / 10.0, + devmode->dmPaperLength / 10.0, GTK_UNIT_MM); gtk_print_settings_set_paper_size (settings, paper_size); gtk_paper_size_free (paper_size); } if (devmode->dmFields & DM_SCALE) - gtk_print_settings_set_scale (settings, - devmode->dmScale / 100.0); + gtk_print_settings_set_scale (settings, devmode->dmScale); if (devmode->dmFields & DM_COPIES) gtk_print_settings_set_n_copies (settings, @@ -748,7 +805,7 @@ devmode_to_settings (GtkPrintSettings *settings, } if (devmode->dmFields & DM_COLOR) - gtk_print_settings_set_use_color (settings, devmode->dmFields == DMCOLOR_COLOR); + gtk_print_settings_set_use_color (settings, devmode->dmColor == DMCOLOR_COLOR); if (devmode->dmFields & DM_DUPLEX) { @@ -830,7 +887,7 @@ static void dialog_to_print_settings (GtkPrintOperation *op, LPPRINTDLGEXW printdlgex) { - int i; + guint i; GtkPrintSettings *settings; settings = gtk_print_settings_new (); @@ -902,8 +959,8 @@ devmode_from_settings (GtkPrintSettings *settings, { devmode->dmDriverExtra = extras_len; memcpy (((char *)devmode) + sizeof (DEVMODEW), extras, extras_len); - g_free (extras); } + g_free (extras); if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION)) devmode->dmDriverVersion = gtk_print_settings_get_int (settings, GTK_PRINT_SETTINGS_WIN32_DRIVER_VERSION); @@ -940,8 +997,10 @@ devmode_from_settings (GtkPrintSettings *settings, { devmode->dmPaperSize = DMPAPER_USER; devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH; - devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) / 10.0; - devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) / 10.0; + + /* Lengths in DEVMODE are in tenths of a millimeter */ + devmode->dmPaperWidth = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM) * 10.0; + devmode->dmPaperLength = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM) * 10.0; } gtk_paper_size_free (paper_size); } @@ -949,7 +1008,7 @@ devmode_from_settings (GtkPrintSettings *settings, if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_SCALE)) { devmode->dmFields |= DM_SCALE; - devmode->dmScale = gtk_print_settings_get_scale (settings) * 100; + devmode->dmScale = gtk_print_settings_get_scale (settings); } if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_N_COPIES)) @@ -1159,7 +1218,7 @@ dialog_from_print_settings (GtkPrintOperation *op, printer = gtk_print_settings_get_printer (settings); if (printer) - printdlgex->hDevNames = gtk_print_win32_devnames_from_printer_name (printer); + printdlgex->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer); printdlgex->hDevMode = devmode_from_settings (settings, op->priv->default_page_setup); @@ -1278,8 +1337,8 @@ plug_grab_notify (GtkWidget *widget, gboolean was_grabbed, GtkPrintOperation *op) { - EnableWindow(GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT), - was_grabbed); + EnableWindow (GetAncestor (GDK_WINDOW_HWND (gtk_widget_get_window (widget)), GA_ROOT), + was_grabbed); } @@ -1297,14 +1356,15 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) op = GTK_PRINT_OPERATION ((gpointer)page->lParam); op_win32 = op->priv->platform_data; - SetWindowLongPtrW(wnd, GWLP_USERDATA, (LONG_PTR)op); + SetWindowLongPtrW (wnd, GWLP_USERDATA, (LONG_PTR)op); - plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd); + plug = _gtk_win32_embed_widget_new (wnd); + gtk_window_set_modal (GTK_WINDOW (plug), TRUE); op_win32->embed_widget = plug; gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget); gtk_widget_show (op->priv->custom_widget); gtk_widget_show (plug); - gdk_window_focus (plug->window, GDK_CURRENT_TIME); + gdk_window_focus (gtk_widget_get_window (plug), GDK_CURRENT_TIME); /* This dialog is modal, so we grab the embed widget */ gtk_grab_add (plug); @@ -1315,7 +1375,7 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) } else if (message == WM_DESTROY) { - op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA)); + op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA)); op_win32 = op->priv->platform_data; g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget); @@ -1325,7 +1385,7 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) } else { - op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA)); + op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA)); op_win32 = op->priv->platform_data; return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget), @@ -1346,45 +1406,49 @@ create_application_page (GtkPrintOperation *op) WORD baseunitX, baseunitY; WORD *array; GtkRequisition requisition; - const char *app_name; + const char *tab_label; /* Make the template the size of the custom widget size request */ - gtk_widget_size_request (op->priv->custom_widget, &requisition); - - base_units = GetDialogBaseUnits(); - baseunitX = LOWORD(base_units); - baseunitY = HIWORD(base_units); + gtk_widget_get_preferred_size (op->priv->custom_widget, + &requisition, NULL); + + base_units = GetDialogBaseUnits (); + baseunitX = LOWORD (base_units); + baseunitY = HIWORD (base_units); htemplate = GlobalAlloc (GMEM_MOVEABLE, - sizeof (DLGTEMPLATE) + sizeof(WORD) * 3); + sizeof (DLGTEMPLATE) + sizeof (WORD) * 3); template = GlobalLock (htemplate); template->style = WS_CHILDWINDOW | DS_CONTROL; template->dwExtendedStyle = WS_EX_CONTROLPARENT; template->cdit = 0; - template->x = MulDiv(0, 4, baseunitX); - template->y = MulDiv(0, 8, baseunitY); - template->cx = MulDiv(requisition.width, 4, baseunitX); - template->cy = MulDiv(requisition.height, 8, baseunitY); + template->x = MulDiv (0, 4, baseunitX); + template->y = MulDiv (0, 8, baseunitY); + template->cx = MulDiv (requisition.width, 4, baseunitX); + template->cy = MulDiv (requisition.height, 8, baseunitY); array = (WORD *) (template+1); *array++ = 0; /* menu */ *array++ = 0; /* class */ *array++ = 0; /* title */ - memset(&page, 0, sizeof (page)); + memset (&page, 0, sizeof (page)); page.dwSize = sizeof (page); page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE; page.hInstance = GetModuleHandle (NULL); page.pResource = template; - app_name = g_get_application_name (); - if (app_name == NULL) - app_name = _("Application"); - page.pszTitle = g_utf8_to_utf16 (app_name, + + tab_label = op->priv->custom_tab_label; + if (tab_label == NULL) + tab_label = g_get_application_name (); + if (tab_label == NULL) + tab_label = _("Application"); + page.pszTitle = g_utf8_to_utf16 (tab_label, -1, NULL, NULL, NULL); page.pfnDlgProc = pageDlgProc; page.pfnCallback = NULL; page.lParam = (LPARAM) op; - hpage = CreatePropertySheetPageW(&page); + hpage = CreatePropertySheetPageW (&page); GlobalUnlock (htemplate); @@ -1393,11 +1457,193 @@ create_application_page (GtkPrintOperation *op) return hpage; } +static GtkPageSetup * +create_page_setup (GtkPrintOperation *op) +{ + GtkPrintOperationPrivate *priv = op->priv; + GtkPageSetup *page_setup; + GtkPrintSettings *settings; + + if (priv->default_page_setup) + page_setup = gtk_page_setup_copy (priv->default_page_setup); + else + page_setup = gtk_page_setup_new (); + + settings = priv->print_settings; + if (settings) + { + GtkPaperSize *paper_size; + + if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION)) + gtk_page_setup_set_orientation (page_setup, + gtk_print_settings_get_orientation (settings)); + + + paper_size = gtk_print_settings_get_paper_size (settings); + if (paper_size) + { + gtk_page_setup_set_paper_size (page_setup, paper_size); + gtk_paper_size_free (paper_size); + } + + /* TODO: Margins? */ + } + + return page_setup; +} + GtkPrintOperationResult -_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, - GtkWindow *parent, - gboolean *do_print, - GError **error) +gtk_print_operation_run_without_dialog (GtkPrintOperation *op, + gboolean *do_print) +{ + GtkPrintOperationResult result; + GtkPrintOperationWin32 *op_win32; + GtkPrintOperationPrivate *priv; + GtkPrintSettings *settings; + GtkPageSetup *page_setup; + DOCINFOW docinfo; + HGLOBAL hDevMode = NULL; + HGLOBAL hDevNames = NULL; + HDC hDC = NULL; + const char *printer = NULL; + double dpi_x, dpi_y; + int job_id; + cairo_t *cr; + DEVNAMES *pdn; + DEVMODEW *pdm; + + *do_print = FALSE; + + priv = op->priv; + settings = priv->print_settings; + + op_win32 = g_new0 (GtkPrintOperationWin32, 1); + priv->platform_data = op_win32; + priv->free_platform_data = (GDestroyNotify) op_win32_free; + printer = gtk_print_settings_get_printer (settings); + + if (!printer) + { + /* No printer selected. Get the system default printer and store + * it in settings. + */ + gchar *tmp_printer = get_default_printer (); + if (!tmp_printer) + { + result = GTK_PRINT_OPERATION_RESULT_ERROR; + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_INTERNAL_ERROR, + _("No printer found")); + goto out; + } + gtk_print_settings_set_printer (settings, tmp_printer); + printer = gtk_print_settings_get_printer (settings); + g_free (tmp_printer); + } + + hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer); + hDevMode = devmode_from_settings (settings, op->priv->default_page_setup); + + /* Create a printer DC for the print settings and page setup provided. */ + pdn = GlobalLock (hDevNames); + pdm = GlobalLock (hDevMode); + hDC = CreateDCW ((wchar_t*)pdn + pdn->wDriverOffset, + (wchar_t*)pdn + pdn->wDeviceOffset, + (wchar_t*)pdn + pdn->wOutputOffset, + pdm ); + GlobalUnlock (hDevNames); + GlobalUnlock (hDevMode); + + if (!hDC) + { + result = GTK_PRINT_OPERATION_RESULT_ERROR; + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_INTERNAL_ERROR, + _("Invalid argument to CreateDC")); + goto out; + } + + priv->print_context = _gtk_print_context_new (op); + page_setup = create_page_setup (op); + _gtk_print_context_set_page_setup (priv->print_context, page_setup); + g_object_unref (page_setup); + + *do_print = TRUE; + + op_win32->surface = cairo_win32_printing_surface_create (hDC); + dpi_x = (double) GetDeviceCaps (hDC, LOGPIXELSX); + dpi_y = (double) GetDeviceCaps (hDC, LOGPIXELSY); + + cr = cairo_create (op_win32->surface); + gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y); + cairo_destroy (cr); + + set_hard_margins (op); + + memset (&docinfo, 0, sizeof (DOCINFOW)); + docinfo.cbSize = sizeof (DOCINFOW); + docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); + docinfo.lpszOutput = NULL; + docinfo.lpszDatatype = NULL; + docinfo.fwType = 0; + + job_id = StartDocW (hDC, &docinfo); + g_free ((void *)docinfo.lpszDocName); + if (job_id <= 0) + { + result = GTK_PRINT_OPERATION_RESULT_ERROR; + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_GENERAL, + _("Error from StartDoc")); + *do_print = FALSE; + cairo_surface_destroy (op_win32->surface); + op_win32->surface = NULL; + goto out; + } + + result = GTK_PRINT_OPERATION_RESULT_APPLY; + op_win32->hdc = hDC; + op_win32->devmode = hDevMode; + op_win32->devnames = hDevNames; + op_win32->job_id = job_id; + op->priv->print_pages = gtk_print_settings_get_print_pages (op->priv->print_settings); + op->priv->num_page_ranges = 0; + if (op->priv->print_pages == GTK_PRINT_PAGES_RANGES) + op->priv->page_ranges = gtk_print_settings_get_page_ranges (op->priv->print_settings, + &op->priv->num_page_ranges); + op->priv->manual_num_copies = 1; + op->priv->manual_collation = FALSE; + op->priv->manual_reverse = FALSE; + op->priv->manual_orientation = FALSE; + op->priv->manual_scale = 1.0; + op->priv->manual_page_set = GTK_PAGE_SET_ALL; + op->priv->manual_number_up = 1; + op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM; + + op->priv->start_page = win32_start_page; + op->priv->end_page = win32_end_page; + op->priv->end_run = win32_end_run; + + out: + if (!*do_print && hDC != NULL) + DeleteDC (hDC); + + if (!*do_print && hDevMode != NULL) + GlobalFree (hDevMode); + + if (!*do_print && hDevNames != NULL) + GlobalFree (hDevNames); + + return result; +} + +GtkPrintOperationResult +gtk_print_operation_run_with_dialog (GtkPrintOperation *op, + GtkWindow *parent, + gboolean *do_print) { HRESULT hResult; LPPRINTDLGEXW printdlgex = NULL; @@ -1406,14 +1652,17 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, GtkWidget *invisible = NULL; GtkPrintOperationResult result; GtkPrintOperationWin32 *op_win32; + GtkPrintOperationPrivate *priv; IPrintDialogCallback *callback; HPROPSHEETPAGE prop_page; *do_print = FALSE; + priv = op->priv; + op_win32 = g_new0 (GtkPrintOperationWin32, 1); - op->priv->platform_data = op_win32; - op->priv->free_platform_data = (GDestroyNotify) op_win32_free; + priv->platform_data = op_win32; + priv->free_platform_data = (GDestroyNotify) op_win32_free; if (parent == NULL) { @@ -1427,14 +1676,14 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, if (!printdlgex) { result = GTK_PRINT_OPERATION_RESULT_ERROR; - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_NOMEM, - _("Not enough free memory")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_NOMEM, + _("Not enough free memory")); goto out; } - printdlgex->lStructSize = sizeof(PRINTDLGEXW); + printdlgex->lStructSize = sizeof (PRINTDLGEXW); printdlgex->hwndOwner = parentHWnd; printdlgex->hDevMode = NULL; printdlgex->hDevNames = NULL; @@ -1450,10 +1699,10 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, if (!page_ranges) { result = GTK_PRINT_OPERATION_RESULT_ERROR; - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_NOMEM, - _("Not enough free memory")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_NOMEM, + _("Not enough free memory")); goto out; } @@ -1490,7 +1739,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, printdlgex->lpCallback = (IUnknown *)callback; got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS"); - hResult = PrintDlgExW(printdlgex); + hResult = PrintDlgExW (printdlgex); IUnknown_Release ((IUnknown *)callback); gdk_win32_set_modal_dialog_libgtk_only (NULL); @@ -1498,30 +1747,30 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, { result = GTK_PRINT_OPERATION_RESULT_ERROR; if (hResult == E_OUTOFMEMORY) - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_NOMEM, - _("Not enough free memory")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_NOMEM, + _("Not enough free memory")); else if (hResult == E_INVALIDARG) - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_INTERNAL_ERROR, - _("Invalid argument to PrintDlgEx")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_INTERNAL_ERROR, + _("Invalid argument to PrintDlgEx")); else if (hResult == E_POINTER) - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_INTERNAL_ERROR, - _("Invalid pointer to PrintDlgEx")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_INTERNAL_ERROR, + _("Invalid pointer to PrintDlgEx")); else if (hResult == E_HANDLE) - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_INTERNAL_ERROR, - _("Invalid handle to PrintDlgEx")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_INTERNAL_ERROR, + _("Invalid handle to PrintDlgEx")); else /* E_FAIL */ - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_GENERAL, - _("Unspecified error")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_GENERAL, + _("Unspecified error")); goto out; } @@ -1538,32 +1787,47 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, { DOCINFOW docinfo; int job_id; - + double dpi_x, dpi_y; + cairo_t *cr; + GtkPageSetup *page_setup; + + priv->print_context = _gtk_print_context_new (op); + page_setup = create_page_setup (op); + _gtk_print_context_set_page_setup (priv->print_context, page_setup); + g_object_unref (page_setup); + *do_print = TRUE; - op->priv->surface = cairo_win32_surface_create (printdlgex->hDC); - op->priv->dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX); - op->priv->dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY); + op_win32->surface = cairo_win32_printing_surface_create (printdlgex->hDC); - memset( &docinfo, 0, sizeof (DOCINFOW)); + dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX); + dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY); + + cr = cairo_create (op_win32->surface); + gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y); + cairo_destroy (cr); + + set_hard_margins (op); + + memset ( &docinfo, 0, sizeof (DOCINFOW)); docinfo.cbSize = sizeof (DOCINFOW); docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); docinfo.lpszOutput = (LPCWSTR) NULL; docinfo.lpszDatatype = (LPCWSTR) NULL; docinfo.fwType = 0; - job_id = StartDocW(printdlgex->hDC, &docinfo); + job_id = StartDocW (printdlgex->hDC, &docinfo); g_free ((void *)docinfo.lpszDocName); if (job_id <= 0) - { + { result = GTK_PRINT_OPERATION_RESULT_ERROR; - g_set_error (error, - GTK_PRINT_ERROR, - GTK_PRINT_ERROR_GENERAL, - _("Error from StartDoc")); + g_set_error_literal (&priv->error, + GTK_PRINT_ERROR, + GTK_PRINT_ERROR_GENERAL, + _("Error from StartDoc")); *do_print = FALSE; - cairo_surface_destroy (op->priv->surface); - op->priv->surface = NULL; + cairo_surface_destroy (op_win32->surface); + op_win32->surface = NULL; goto out; } @@ -1583,6 +1847,8 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, op->priv->manual_orientation = FALSE; op->priv->manual_scale = 1.0; op->priv->manual_page_set = GTK_PAGE_SET_ALL; + op->priv->manual_number_up = 1; + op->priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM; } op->priv->start_page = win32_start_page; @@ -1590,11 +1856,14 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, op->priv->end_run = win32_end_run; out: + if (!*do_print && printdlgex && printdlgex->hDC != NULL) + DeleteDC (printdlgex->hDC); + if (!*do_print && printdlgex && printdlgex->hDevMode != NULL) - GlobalFree(printdlgex->hDevMode); + GlobalFree (printdlgex->hDevMode); if (!*do_print && printdlgex && printdlgex->hDevNames != NULL) - GlobalFree(printdlgex->hDevNames); + GlobalFree (printdlgex->hDevNames); if (page_ranges) GlobalFree (page_ranges); @@ -1608,18 +1877,114 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, return result; } -void -_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op, - GtkWindow *parent, - GtkPrintOperationPrintFunc print_cb) +GtkPrintOperationResult +_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, + gboolean show_dialog, + GtkWindow *parent, + gboolean *do_print) { - gboolean do_print; - - _gtk_print_operation_platform_backend_run_dialog (op, parent, &do_print, NULL); - if (do_print) - print_cb (op, parent, FALSE); + if (show_dialog) + return gtk_print_operation_run_with_dialog (op, parent, do_print); else - _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL); + return gtk_print_operation_run_without_dialog (op, do_print); +} + +void +_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op, + cairo_surface_t *surface, + GtkWindow *parent, + const gchar *filename) +{ + HDC dc; + HENHMETAFILE metafile; + + dc = cairo_win32_surface_get_dc (surface); + cairo_surface_destroy (surface); + metafile = CloseEnhMetaFile (dc); + DeleteEnhMetaFile (metafile); + + ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW); +} + +void +_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op, + cairo_surface_t *surface, + cairo_t *cr) +{ + HDC dc = cairo_win32_surface_get_dc (surface); + StartPage (dc); +} + +void +_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op, + cairo_surface_t *surface, + cairo_t *cr) +{ + HDC dc; + + cairo_surface_show_page (surface); + + /* TODO: Enhanced metafiles don't support multiple pages. + */ + dc = cairo_win32_surface_get_dc (surface); + EndPage (dc); +} + +cairo_surface_t * +_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op, + GtkPageSetup *page_setup, + gdouble *dpi_x, + gdouble *dpi_y, + gchar **target) +{ + GtkPaperSize *paper_size; + HDC metafile_dc; + RECT rect; + char *template; + char *filename; + gunichar2 *filename_utf16; + int fd; + + template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL); + fd = g_mkstemp (template); + close (fd); + + filename = g_strconcat (template, ".emf", NULL); + g_free (template); + + filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); + g_free (filename); + + paper_size = gtk_page_setup_get_paper_size (page_setup); + + /* The rectangle dimensions are given in hundredths of a millimeter */ + rect.left = 0; + rect.right = 100.0 * gtk_paper_size_get_width (paper_size, GTK_UNIT_MM); + rect.top = 0; + rect.bottom = 100.0 * gtk_paper_size_get_height (paper_size, GTK_UNIT_MM); + + metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16, + &rect, L"Gtk+\0Print Preview\0\0"); + if (metafile_dc == NULL) + { + g_warning ("Can't create metafile"); + return NULL; + } + + *target = (char *)filename_utf16; + + *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX); + *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY); + + return cairo_win32_printing_surface_create (metafile_dc); +} + +void +_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op, + GtkPageSetup *page_setup, + cairo_surface_t *surface) +{ + /* TODO: Implement */ } GtkPageSetup * @@ -1649,7 +2014,7 @@ gtk_print_run_page_setup_dialog (GtkWindow *parent, memset (pagesetupdlg, 0, sizeof (PAGESETUPDLGW)); - pagesetupdlg->lStructSize = sizeof(PAGESETUPDLGW); + pagesetupdlg->lStructSize = sizeof (PAGESETUPDLGW); if (parent != NULL) pagesetupdlg->hwndOwner = get_parent_hwnd (GTK_WIDGET (parent)); @@ -1661,10 +2026,10 @@ gtk_print_run_page_setup_dialog (GtkWindow *parent, pagesetupdlg->hDevNames = NULL; printer = gtk_print_settings_get_printer (settings); if (printer) - pagesetupdlg->hDevNames = gtk_print_win32_devnames_from_printer_name (printer); + pagesetupdlg->hDevNames = gtk_print_win32_devnames_to_win32_from_printer_name (printer); - GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER, - (LPWSTR)&measure_system, sizeof (DWORD)); + GetLocaleInfoW (LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER, + (LPWSTR)&measure_system, sizeof (DWORD)); if (measure_system == 0) { @@ -1712,9 +2077,6 @@ gtk_print_run_page_setup_dialog (GtkWindow *parent, devmode_to_settings (settings, pagesetupdlg->hDevMode); } - if (free_settings) - g_object_unref (settings); - if (res) { gtk_page_setup_set_orientation (page_setup, @@ -1751,6 +2113,9 @@ gtk_print_run_page_setup_dialog (GtkWindow *parent, unit); } + if (free_settings) + g_object_unref (settings); + return page_setup; }