more leaks plugged and more *_OPTIONAL
[dia.git] / app / paginate_gdiprint.cpp
blob6b647afac4b7dc8d232281194b5ca4e0ce6f6e19
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998, 1999 Alexander Larsson
4 * paginate_gdiprint.c -- pagination code for the win32 GDI. Rendering
5 * is done by the WMF plug-in.
7 * based on :
8 * paginate_gnomeprint.[ch] -- pagination code for the gnome-print backend
9 * Copyright (C) 1999 James Henstridge
11 * the rest is :
12 * Copyright 2001 Hans Breuer <Hans@Breuer.Org>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <glib.h>
30 #include <math.h>
31 #include <string.h>
33 #ifdef __GNUC__
35 * Super dirty: hide g++ keyword(?) 'export'
36 * otherwise we get:
37 * ../lib/filter.h:35: declaration does not declare anything
38 * ../lib/filter.h:35: parse error before `export'
40 #define export Export
41 #endif
43 extern "C" {
45 #include "paginate_gdiprint.h"
47 #include "diagram.h"
48 #include "diagramdata.h"
50 #include "filter.h"
52 #include "message.h"
56 namespace W32 {
57 #include <windows.h>
60 #define ERROR_RETURN(err) \
61 { \
62 char *msg = g_win32_error_message(err); \
63 message_error(msg); \
64 g_free(msg); \
65 return; \
68 static guint
69 print_page(DiagramData *data, DiaExportFilter* pExp, W32::HANDLE hDC,
70 Rectangle *bounds, gint xpos, gint ypos)
72 guint nobjs = 0;
73 DiagramData page_data = *data; /* ugliness! */
74 page_data.extents = *bounds;
76 /* transform coordinate system */
77 if (data->paper.is_portrait) {
78 } else {
81 /* set up clip mask ? */
83 /* render the region */
84 W32::StartPage((W32::HDC)hDC);
85 pExp->export(&page_data, "", "", (W32::HDC)hDC);
86 W32::EndPage((W32::HDC)hDC);
88 return nobjs;
91 static void
92 paginate_gdiprint(Diagram *dia, DiaExportFilter* pExp, W32::HANDLE hDC)
94 Rectangle *extents;
95 gdouble width, height;
96 gdouble x, y, initx, inity;
97 gint xpos, ypos;
98 guint nobjs = 0;
100 /* the usable area of the page */
101 width = dia->data->paper.width;
102 height = dia->data->paper.height;
104 /* get extents, and make them multiples of width / height */
105 extents = &dia->data->extents;
106 initx = extents->left;
107 inity = extents->top;
108 /* make page boundaries align with origin */
109 if (!dia->data->paper.fitto) {
110 initx = floor(initx / width) * width;
111 inity = floor(inity / height) * height;
114 /* iterate through all the pages in the diagram */
115 for (y = inity, ypos = 0; y < extents->bottom; y += height, ypos++)
116 for (x = initx, xpos = 0; x < extents->right; x += width, xpos++) {
117 Rectangle page_bounds;
119 page_bounds.left = x;
120 page_bounds.right = x + width;
121 page_bounds.top = y;
122 page_bounds.bottom = y + height;
124 nobjs += print_page(dia->data, pExp, hDC, &page_bounds, xpos, ypos);
129 /* to remember changes made in the print dialog, finally leaked. */
130 static W32::HGLOBAL hDevMode = NULL;
131 static W32::HGLOBAL hDevNames = NULL;
133 extern "C"
134 void
135 diagram_print_gdi(Diagram *dia)
137 W32::PRINTDLG printDlg;
138 W32::DOCINFO docInfo;
139 W32::DEVMODE* pDevMode;
140 DiaExportFilter* pExp = NULL;
141 int i;
143 pExp = filter_guess_export_filter("dummy.wmf");
145 if (!pExp) {
146 message_error("Can't print without the WMF plugin installed");
147 return;
150 memset (&printDlg, 0, sizeof (W32::PRINTDLG));
151 printDlg.hDevMode = hDevMode;
152 printDlg.hDevNames = hDevNames;
154 printDlg.Flags = 0;
155 printDlg.nMinPage = printDlg.nMaxPage = 0;
156 printDlg.nCopies = 1;
157 printDlg.lStructSize = sizeof (W32::PRINTDLG);
159 /* Uhmm, first call to initialize device settings ... */
160 if (!printDlg.hDevMode) {
161 printDlg.Flags = PD_RETURNDEFAULT;
162 if (!W32::PrintDlg (&printDlg))
163 g_warning ("Failed to get printer defaults.");
166 pDevMode = (W32::DEVMODE*) W32::GlobalLock (printDlg.hDevMode);
167 if (pDevMode) {
168 /* initialize with Dia default */
169 pDevMode->dmFields |= DM_ORIENTATION;
170 pDevMode->dmOrientation = dia->data->paper.is_portrait ?
171 DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
173 /* Maybe we could adjust the scaling here as well but are al of:
174 * dmPaperSize, dmPaperLength, dmPaperWidth, dmScale
175 * initialized despite of the api documentation ?
177 g_print ("Paper size %d, length %d width %d scale %d\n",
178 pDevMode->dmPaperSize,
179 pDevMode->dmPaperLength, pDevMode->dmPaperWidth, pDevMode->dmScale);
181 W32::GlobalUnlock (printDlg.hDevMode);
184 printDlg.Flags = PD_RETURNDC | PD_NOSELECTION;
186 if (!W32::PrintDlg (&printDlg)) {
187 W32::DWORD dwError = W32::CommDlgExtendedError ();
188 if (dwError)
189 message_error("Print Dialog failed with error %d", dwError);
190 return;
193 /* remember settings made in dialog */
194 hDevMode = printDlg.hDevMode;
195 hDevNames = printDlg.hDevNames;
197 /* check capabilities ? */
198 /* W32::GetDeviceCaps(print_dlg.hDC, RASTERCAPS) */
200 docInfo.cbSize = sizeof(W32::DOCINFO);
201 docInfo.lpszDocName = dia->filename;
202 if (printDlg.Flags & PD_PRINTTOFILE)
203 docInfo.lpszOutput = "FILE:";
204 else
205 docInfo.lpszOutput = NULL; /* use hDC */
206 docInfo.fwType = 0;
207 docInfo.lpszDatatype = NULL;
209 /* finally print */
210 if (0 >= W32::StartDoc(printDlg.hDC, &docInfo))
211 ERROR_RETURN(W32::GetLastError());
212 for (i = 0; i < printDlg.nCopies; i++)
213 paginate_gdiprint(dia, pExp, printDlg.hDC);
215 /* clean up */
216 if (0 >= W32::EndDoc(printDlg.hDC))
217 ERROR_RETURN(W32::GetLastError());