2 |
- |
1 |
/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: gdevwpr2.c,v 1.18 2004/08/05 17:02:36 stefan Exp $ */
|
|
|
18 |
/*
|
|
|
19 |
* Microsoft Windows 3.n printer driver for Ghostscript.
|
|
|
20 |
* Original version by Russell Lang and
|
|
|
21 |
* L. Peter Deutsch, Aladdin Enterprises.
|
|
|
22 |
* Modified by rjl 1995-03-29 to use BMP printer code
|
|
|
23 |
* Modified by Pierre Arnaud 1999-02-18 (see description below)
|
|
|
24 |
* Modified by lpd 1999-04-03 for compatibility with Borland C++ 4.5.
|
|
|
25 |
* Modified by Pierre Arnaud 1999-10-03 (accept b&w printing on color printers).
|
|
|
26 |
* Modified by Pierre Arnaud 1999-11-20 (accept lower resolution)
|
|
|
27 |
* Bug fixed by Pierre Arnaud 2000-03-09 (win_pr2_put_params error when is_open)
|
|
|
28 |
* Bug fixed by Pierre Arnaud 2000-03-20 (win_pr2_set_bpp did not set anti_alias)
|
|
|
29 |
* Bug fixed by Pierre Arnaud 2000-03-22 (win_pr2_set_bpp depth was wrong)
|
|
|
30 |
* Modified by Pierre Arnaud 2000-12-12 (mainly added support for Tumble)
|
|
|
31 |
* Bug fixed by Pierre Arnaud 2000-12-18 (-dQueryUser now works from cmd line)
|
|
|
32 |
*/
|
|
|
33 |
|
|
|
34 |
/* This driver uses the printer default size and resolution and
|
|
|
35 |
* ignores page size and resolution set using -gWIDTHxHEIGHT and
|
|
|
36 |
* -rXxY. You must still set the correct PageSize to get the
|
|
|
37 |
* correct clipping path.
|
|
|
38 |
* The code in win_pr2_getdc() does try to set the printer page
|
|
|
39 |
* size from the PostScript PageSize, but it isn't working
|
|
|
40 |
* reliably at the moment.
|
|
|
41 |
*
|
|
|
42 |
* This driver doesn't work with some Windows printer drivers.
|
|
|
43 |
* The reason is unknown. All printers to which I have access
|
|
|
44 |
* work.
|
|
|
45 |
*
|
|
|
46 |
* rjl 1997-11-20
|
|
|
47 |
*/
|
|
|
48 |
|
|
|
49 |
/* Additions by Pierre Arnaud (Pierre.Arnaud@opac.ch)
|
|
|
50 |
*
|
|
|
51 |
* The driver has been extended in order to provide some run-time
|
|
|
52 |
* feed-back about the default Windows printer and to give the user
|
|
|
53 |
* the opportunity to select the printer's properties before the
|
|
|
54 |
* device gets opened (and any spooling starts).
|
|
|
55 |
*
|
|
|
56 |
* The driver returns an additional property named "UserSettings".
|
|
|
57 |
* This is a dictionary which contens are valid only after setting
|
|
|
58 |
* the QueryUser property (see below). The UserSettings dict contains
|
|
|
59 |
* the following keys:
|
|
|
60 |
*
|
|
|
61 |
* DocumentRange [begin end] (int array, can be set)
|
|
|
62 |
* Defines the range of pages in the document; [1 10] would
|
|
|
63 |
* describe a document starting at page 1 and ending at page 10.
|
|
|
64 |
*
|
|
|
65 |
* SelectedRange [begin end] (int array, can be set)
|
|
|
66 |
* Defines the pages the user wants to print.
|
|
|
67 |
*
|
|
|
68 |
* MediaSize [width height] (float array, read only)
|
|
|
69 |
* Current printer's media size.
|
|
|
70 |
*
|
|
|
71 |
* Copies n (integer, can be set)
|
|
|
72 |
* User selected number of copies.
|
|
|
73 |
*
|
|
|
74 |
* PrintCopies n (integer, read only)
|
|
|
75 |
* Number of copies which must be printed by Ghostscript itself.
|
|
|
76 |
* This is still experimental.
|
|
|
77 |
*
|
|
|
78 |
* DocumentName name (string, can be set)
|
|
|
79 |
* Name to be associated with the print job.
|
|
|
80 |
*
|
|
|
81 |
* UserChangedSettings (bool, read only)
|
|
|
82 |
* Set to 'true' if the last QueryUser operation succeeded.
|
|
|
83 |
*
|
|
|
84 |
* Paper n (integer, can be set)
|
|
|
85 |
* Windows paper selection (0 = automatic).
|
|
|
86 |
*
|
|
|
87 |
* Orient n (integer, can be set)
|
|
|
88 |
* Windows paper orientation (0 = automatic).
|
|
|
89 |
*
|
|
|
90 |
* Color n (integer, can be set)
|
|
|
91 |
* Windows color (0 = automatic, 1 = monochrome, 2 = color).
|
|
|
92 |
*
|
|
|
93 |
* MaxResolution n (integer, can be set)
|
|
|
94 |
* Maximum resolution in pixels pet inch (0 = no maximum). If
|
|
|
95 |
* the printer has a higher resolution than the maximum, trim
|
|
|
96 |
* the used resolution to the best one (dpi_chosen <= dpi_max,
|
|
|
97 |
* with dpi_chosen = dpi_printer / ratio).
|
|
|
98 |
*/
|
|
|
99 |
|
|
|
100 |
/* Supported printer parameters are :
|
|
|
101 |
*
|
|
|
102 |
* -dBitsPerPixel=n
|
|
|
103 |
* Override what the Window printer driver returns.
|
|
|
104 |
*
|
|
|
105 |
* -dNoCancel
|
|
|
106 |
* Don't display cancel dialog box. Useful for unattended or
|
|
|
107 |
* console EXE operation.
|
|
|
108 |
*
|
|
|
109 |
* -dQueryUser=n
|
|
|
110 |
* Query user interactively for the destination printer, before
|
|
|
111 |
* the device gets opened. This fills in the UserSettings dict
|
|
|
112 |
* and the OutputFile name properties. The following values are
|
|
|
113 |
* supported for n:
|
|
|
114 |
* 1 => show standard Print dialog
|
|
|
115 |
* 2 => show Print Setup dialog instead
|
|
|
116 |
* 3 => select default printer
|
|
|
117 |
* other, does nothing
|
|
|
118 |
*
|
|
|
119 |
* The /Duplex & /Tumble keys of the setpagedevice dict are supported
|
|
|
120 |
* if the Windows printer supports duplex printing.
|
|
|
121 |
*/
|
|
|
122 |
|
|
|
123 |
#include "gdevprn.h"
|
|
|
124 |
#include "gdevpccm.h"
|
|
|
125 |
|
|
|
126 |
#include "windows_.h"
|
|
|
127 |
#include <shellapi.h>
|
|
|
128 |
#include "gp_mswin.h"
|
|
|
129 |
|
|
|
130 |
#include "gp.h"
|
|
|
131 |
#include "gpcheck.h"
|
|
|
132 |
#include "commdlg.h"
|
|
|
133 |
|
|
|
134 |
|
|
|
135 |
/* Make sure we cast to the correct structure type. */
|
|
|
136 |
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
|
|
|
137 |
|
|
|
138 |
#undef wdev
|
|
|
139 |
#define wdev ((gx_device_win_pr2 *)dev)
|
|
|
140 |
|
|
|
141 |
/* Device procedures */
|
|
|
142 |
|
|
|
143 |
/* See gxdevice.h for the definitions of the procedures. */
|
|
|
144 |
private dev_proc_open_device(win_pr2_open);
|
|
|
145 |
private dev_proc_close_device(win_pr2_close);
|
|
|
146 |
private dev_proc_print_page(win_pr2_print_page);
|
|
|
147 |
private dev_proc_map_rgb_color(win_pr2_map_rgb_color);
|
|
|
148 |
private dev_proc_map_color_rgb(win_pr2_map_color_rgb);
|
|
|
149 |
private dev_proc_get_params(win_pr2_get_params);
|
|
|
150 |
private dev_proc_put_params(win_pr2_put_params);
|
|
|
151 |
|
|
|
152 |
private void win_pr2_set_bpp(gx_device * dev, int depth);
|
|
|
153 |
|
|
|
154 |
private const gx_device_procs win_pr2_procs =
|
|
|
155 |
prn_color_params_procs(win_pr2_open, gdev_prn_output_page, win_pr2_close,
|
|
|
156 |
win_pr2_map_rgb_color, win_pr2_map_color_rgb,
|
|
|
157 |
win_pr2_get_params, win_pr2_put_params);
|
|
|
158 |
|
|
|
159 |
#define PARENT_WINDOW HWND_DESKTOP
|
|
|
160 |
BOOL CALLBACK CancelDlgProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
161 |
BOOL CALLBACK AbortProc2(HDC, int);
|
|
|
162 |
|
|
|
163 |
|
|
|
164 |
/* The device descriptor */
|
|
|
165 |
typedef struct gx_device_win_pr2_s gx_device_win_pr2;
|
|
|
166 |
struct gx_device_win_pr2_s {
|
|
|
167 |
gx_device_common;
|
|
|
168 |
gx_prn_device_common;
|
|
|
169 |
HDC hdcprn;
|
|
|
170 |
bool nocancel;
|
|
|
171 |
|
|
|
172 |
int doc_page_begin; /* first page number in document */
|
|
|
173 |
int doc_page_end; /* last page number in document */
|
|
|
174 |
int user_page_begin; /* user's choice: first page to print */
|
|
|
175 |
int user_page_end; /* user's choice: last page to print */
|
|
|
176 |
int user_copies; /* user's choice: number of copies */
|
|
|
177 |
int print_copies; /* number of times GS should print each page */
|
|
|
178 |
float user_media_size[2]; /* width/height of media selected by user */
|
|
|
179 |
char doc_name[200]; /* name of document for the spooler */
|
|
|
180 |
char paper_name[64]; /* name of selected paper format */
|
|
|
181 |
bool user_changed_settings; /* true if user validated dialog */
|
|
|
182 |
int user_paper; /* user's choice: paper format */
|
|
|
183 |
int user_orient; /* user's choice: paper orientation */
|
|
|
184 |
int user_color; /* user's choice: color format */
|
|
|
185 |
int max_dpi; /* maximum resolution in DPI */
|
|
|
186 |
int ratio; /* stretch ratio when printing */
|
|
|
187 |
int selected_bpp; /* selected bpp, memorised by win_pr2_set_bpp */
|
|
|
188 |
bool tumble; /* tumble setting (with duplex) */
|
|
|
189 |
int query_user; /* query user (-dQueryUser) */
|
|
|
190 |
|
|
|
191 |
HANDLE win32_hdevmode; /* handle to device mode information */
|
|
|
192 |
HANDLE win32_hdevnames; /* handle to device names information */
|
|
|
193 |
|
|
|
194 |
DLGPROC lpfnAbortProc;
|
|
|
195 |
DLGPROC lpfnCancelProc;
|
|
|
196 |
HWND hDlgModeless;
|
|
|
197 |
|
|
|
198 |
bool use_old_spool_name; /* user prefers old \\spool\ name */
|
|
|
199 |
gx_device_win_pr2* original_device; /* used to detect copies */
|
|
|
200 |
};
|
|
|
201 |
|
|
|
202 |
gx_device_win_pr2 far_data gs_mswinpr2_device =
|
|
|
203 |
{
|
|
|
204 |
prn_device_std_body(gx_device_win_pr2, win_pr2_procs, "mswinpr2",
|
|
|
205 |
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72.0, 72.0,
|
|
|
206 |
0, 0, 0, 0,
|
|
|
207 |
0, win_pr2_print_page), /* depth = 0 */
|
|
|
208 |
0, /* hdcprn */
|
|
|
209 |
0, /* nocancel */
|
|
|
210 |
0, /* doc_page_begin */
|
|
|
211 |
0, /* doc_page_end */
|
|
|
212 |
0, /* user_page_begin */
|
|
|
213 |
0, /* user_page_end */
|
|
|
214 |
1, /* user_copies */
|
|
|
215 |
1, /* print_copies */
|
|
|
216 |
{ 0.0, 0.0 }, /* user_media_size */
|
|
|
217 |
{ 0 }, /* doc_name */
|
|
|
218 |
{ 0 }, /* paper_name */
|
|
|
219 |
0, /* user_changed_settings */
|
|
|
220 |
0, /* user_paper */
|
|
|
221 |
0, /* user_orient */
|
|
|
222 |
0, /* user_color */
|
|
|
223 |
0, /* max_dpi */
|
|
|
224 |
0, /* ratio */
|
|
|
225 |
0, /* selected_bpp */
|
|
|
226 |
false, /* tumble */
|
|
|
227 |
-1, /* query_user */
|
|
|
228 |
NULL, /* win32_hdevmode */
|
|
|
229 |
NULL, /* win32_hdevnames */
|
|
|
230 |
NULL, /* lpfnAbortProc */
|
|
|
231 |
NULL, /* lpfnCancelProc */
|
|
|
232 |
NULL, /* hDlgModeless */
|
|
|
233 |
false, /* use_old_spool_name */
|
|
|
234 |
NULL /* original_device */
|
|
|
235 |
};
|
|
|
236 |
|
|
|
237 |
/********************************************************************************/
|
|
|
238 |
|
|
|
239 |
private int win_pr2_getdc(gx_device_win_pr2 * dev);
|
|
|
240 |
private int win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
|
|
|
241 |
private int win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
|
|
|
242 |
private int win_pr2_print_setup_interaction(gx_device_win_pr2 * dev, int mode);
|
|
|
243 |
private int win_pr2_write_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
|
|
|
244 |
private int win_pr2_read_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
|
|
|
245 |
private void win_pr2_copy_check(gx_device_win_pr2 * dev);
|
|
|
246 |
|
|
|
247 |
/********************************************************************************/
|
|
|
248 |
|
|
|
249 |
/* Open the win_pr2 driver */
|
|
|
250 |
private int
|
|
|
251 |
win_pr2_open(gx_device * dev)
|
|
|
252 |
{
|
|
|
253 |
int code;
|
|
|
254 |
int depth;
|
|
|
255 |
PRINTDLG pd;
|
|
|
256 |
POINT offset;
|
|
|
257 |
POINT size;
|
|
|
258 |
float m[4];
|
|
|
259 |
FILE *pfile;
|
|
|
260 |
DOCINFO docinfo;
|
|
|
261 |
float ratio = 1.0;
|
|
|
262 |
|
|
|
263 |
win_pr2_copy_check(wdev);
|
|
|
264 |
|
|
|
265 |
/* get a HDC for the printer */
|
|
|
266 |
if ((wdev->win32_hdevmode) &&
|
|
|
267 |
(wdev->win32_hdevnames)) {
|
|
|
268 |
/* The user has already had the opportunity to choose the output */
|
|
|
269 |
/* file interactively. Just use the specified parameters. */
|
|
|
270 |
|
|
|
271 |
LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
|
|
|
272 |
LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
|
|
|
273 |
|
|
|
274 |
const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
|
|
|
275 |
const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
|
|
|
276 |
const char* output = (char*)(devnames)+(devnames->wOutputOffset);
|
|
|
277 |
|
|
|
278 |
wdev->hdcprn = CreateDC(driver, device, output, devmode);
|
|
|
279 |
|
|
|
280 |
GlobalUnlock(wdev->win32_hdevmode);
|
|
|
281 |
GlobalUnlock(wdev->win32_hdevnames);
|
|
|
282 |
|
|
|
283 |
if (wdev->hdcprn == NULL) {
|
|
|
284 |
return gs_error_Fatal;
|
|
|
285 |
}
|
|
|
286 |
|
|
|
287 |
} else if (!win_pr2_getdc(wdev)) {
|
|
|
288 |
/* couldn't get a printer from -sOutputFile= */
|
|
|
289 |
/* Prompt with dialog box */
|
|
|
290 |
|
|
|
291 |
LPDEVMODE devmode = NULL;
|
|
|
292 |
memset(&pd, 0, sizeof(pd));
|
|
|
293 |
|
|
|
294 |
pd.lStructSize = sizeof(pd);
|
|
|
295 |
pd.hwndOwner = PARENT_WINDOW;
|
|
|
296 |
pd.Flags = PD_RETURNDC;
|
|
|
297 |
pd.nMinPage = wdev->doc_page_begin;
|
|
|
298 |
pd.nMaxPage = wdev->doc_page_end;
|
|
|
299 |
pd.nFromPage = wdev->user_page_begin;
|
|
|
300 |
pd.nToPage = wdev->user_page_end;
|
|
|
301 |
pd.nCopies = wdev->user_copies;
|
|
|
302 |
|
|
|
303 |
if (!PrintDlg(&pd)) {
|
|
|
304 |
/* device not opened - exit ghostscript */
|
|
|
305 |
return gs_error_Fatal; /* exit Ghostscript cleanly */
|
|
|
306 |
}
|
|
|
307 |
|
|
|
308 |
devmode = GlobalLock(pd.hDevMode);
|
|
|
309 |
win_pr2_update_dev(wdev,devmode);
|
|
|
310 |
GlobalUnlock(pd.hDevMode);
|
|
|
311 |
|
|
|
312 |
if (wdev->win32_hdevmode)
|
|
|
313 |
GlobalFree(wdev->win32_hdevmode);
|
|
|
314 |
if (wdev->win32_hdevnames)
|
|
|
315 |
GlobalFree(wdev->win32_hdevnames);
|
|
|
316 |
|
|
|
317 |
wdev->hdcprn = pd.hDC;
|
|
|
318 |
wdev->win32_hdevmode = pd.hDevMode;
|
|
|
319 |
wdev->win32_hdevnames = pd.hDevNames;
|
|
|
320 |
|
|
|
321 |
pd.hDevMode = NULL;
|
|
|
322 |
pd.hDevNames = NULL;
|
|
|
323 |
}
|
|
|
324 |
if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_DIBTODEV)) {
|
|
|
325 |
errprintf( "Windows printer does not have RC_DIBTODEV\n");
|
|
|
326 |
DeleteDC(wdev->hdcprn);
|
|
|
327 |
return gs_error_limitcheck;
|
|
|
328 |
}
|
|
|
329 |
/* initialise printer, install abort proc */
|
|
|
330 |
wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
|
|
|
331 |
SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);
|
|
|
332 |
|
|
|
333 |
/*
|
|
|
334 |
* Some versions of the Windows headers include lpszDatatype and fwType,
|
|
|
335 |
* and some don't. Since we want to set these fields to zero anyway,
|
|
|
336 |
* we just start by zeroing the whole structure.
|
|
|
337 |
*/
|
|
|
338 |
memset(&docinfo, 0, sizeof(docinfo));
|
|
|
339 |
docinfo.cbSize = sizeof(docinfo);
|
|
|
340 |
docinfo.lpszDocName = wdev->doc_name;
|
|
|
341 |
/*docinfo.lpszOutput = NULL;*/
|
|
|
342 |
/*docinfo.lpszDatatype = NULL;*/
|
|
|
343 |
/*docinfo.fwType = 0;*/
|
|
|
344 |
|
|
|
345 |
if (docinfo.lpszDocName[0] == 0) {
|
|
|
346 |
docinfo.lpszDocName = "Ghostscript output";
|
|
|
347 |
}
|
|
|
348 |
|
|
|
349 |
if (StartDoc(wdev->hdcprn, &docinfo) <= 0) {
|
|
|
350 |
errprintf("Printer StartDoc failed (error %08x)\n", GetLastError());
|
|
|
351 |
DeleteDC(wdev->hdcprn);
|
|
|
352 |
return gs_error_limitcheck;
|
|
|
353 |
}
|
|
|
354 |
|
|
|
355 |
dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
|
|
|
356 |
dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
|
|
|
357 |
|
|
|
358 |
wdev->ratio = 1;
|
|
|
359 |
|
|
|
360 |
if (wdev->max_dpi > 50) {
|
|
|
361 |
|
|
|
362 |
float dpi_x = dev->x_pixels_per_inch;
|
|
|
363 |
float dpi_y = dev->y_pixels_per_inch;
|
|
|
364 |
|
|
|
365 |
while ((dev->x_pixels_per_inch > wdev->max_dpi)
|
|
|
366 |
|| (dev->y_pixels_per_inch > wdev->max_dpi)) {
|
|
|
367 |
ratio += 1.0;
|
|
|
368 |
wdev->ratio ++;
|
|
|
369 |
dev->x_pixels_per_inch = dpi_x / ratio;
|
|
|
370 |
dev->y_pixels_per_inch = dpi_y / ratio;
|
|
|
371 |
}
|
|
|
372 |
}
|
|
|
373 |
|
|
|
374 |
size.x = GetDeviceCaps(wdev->hdcprn, PHYSICALWIDTH);
|
|
|
375 |
size.y = GetDeviceCaps(wdev->hdcprn, PHYSICALHEIGHT);
|
|
|
376 |
gx_device_set_width_height(dev, (int)(size.x / ratio), (int)(size.y / ratio));
|
|
|
377 |
offset.x = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETX);
|
|
|
378 |
offset.y = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETY);
|
|
|
379 |
|
|
|
380 |
/* m[] gives margins in inches */
|
|
|
381 |
m[0] /*left */ = offset.x / dev->x_pixels_per_inch / ratio;
|
|
|
382 |
m[3] /*top */ = offset.y / dev->y_pixels_per_inch / ratio;
|
|
|
383 |
m[2] /*right */ = (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES)) / dev->x_pixels_per_inch / ratio;
|
|
|
384 |
m[1] /*bottom */ = (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES)) / dev->y_pixels_per_inch / ratio;
|
|
|
385 |
gx_device_set_margins(dev, m, true);
|
|
|
386 |
|
|
|
387 |
depth = dev->color_info.depth;
|
|
|
388 |
if (depth == 0) {
|
|
|
389 |
/* Set parameters that were unknown before opening device */
|
|
|
390 |
/* Find out if the device supports color */
|
|
|
391 |
/* We recognize 1, 4 (but use only 3), 8 and 24 bit color devices */
|
|
|
392 |
depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
|
|
|
393 |
}
|
|
|
394 |
win_pr2_set_bpp(dev, depth);
|
|
|
395 |
|
|
|
396 |
/* gdev_prn_open opens a temporary file which we don't want */
|
|
|
397 |
/* so we specify the name now so we can delete it later */
|
|
|
398 |
pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
|
|
|
399 |
wdev->fname, "wb");
|
|
|
400 |
fclose(pfile);
|
|
|
401 |
code = gdev_prn_open(dev);
|
|
|
402 |
/* delete unwanted temporary file */
|
|
|
403 |
unlink(wdev->fname);
|
|
|
404 |
|
|
|
405 |
if (!wdev->nocancel) {
|
|
|
406 |
/* inform user of progress with dialog box and allow cancel */
|
|
|
407 |
wdev->lpfnCancelProc = (DLGPROC) CancelDlgProc;
|
|
|
408 |
wdev->hDlgModeless = CreateDialog(phInstance, "CancelDlgBox",
|
|
|
409 |
PARENT_WINDOW, wdev->lpfnCancelProc);
|
|
|
410 |
ShowWindow(wdev->hDlgModeless, SW_HIDE);
|
|
|
411 |
}
|
|
|
412 |
return code;
|
|
|
413 |
};
|
|
|
414 |
|
|
|
415 |
/* Close the win_pr2 driver */
|
|
|
416 |
private int
|
|
|
417 |
win_pr2_close(gx_device * dev)
|
|
|
418 |
{
|
|
|
419 |
int code;
|
|
|
420 |
int aborted = FALSE;
|
|
|
421 |
|
|
|
422 |
win_pr2_copy_check(wdev);
|
|
|
423 |
|
|
|
424 |
/* Free resources */
|
|
|
425 |
|
|
|
426 |
if (!wdev->nocancel) {
|
|
|
427 |
if (!wdev->hDlgModeless)
|
|
|
428 |
aborted = TRUE;
|
|
|
429 |
else
|
|
|
430 |
DestroyWindow(wdev->hDlgModeless);
|
|
|
431 |
wdev->hDlgModeless = 0;
|
|
|
432 |
}
|
|
|
433 |
if (aborted)
|
|
|
434 |
AbortDoc(wdev->hdcprn);
|
|
|
435 |
else
|
|
|
436 |
EndDoc(wdev->hdcprn);
|
|
|
437 |
|
|
|
438 |
DeleteDC(wdev->hdcprn);
|
|
|
439 |
|
|
|
440 |
if (wdev->win32_hdevmode != NULL) {
|
|
|
441 |
GlobalFree(wdev->win32_hdevmode);
|
|
|
442 |
wdev->win32_hdevmode = NULL;
|
|
|
443 |
}
|
|
|
444 |
if (wdev->win32_hdevnames != NULL) {
|
|
|
445 |
GlobalFree(wdev->win32_hdevnames);
|
|
|
446 |
wdev->win32_hdevnames = NULL;
|
|
|
447 |
}
|
|
|
448 |
|
|
|
449 |
code = gdev_prn_close(dev);
|
|
|
450 |
return code;
|
|
|
451 |
}
|
|
|
452 |
|
|
|
453 |
|
|
|
454 |
/* ------ Internal routines ------ */
|
|
|
455 |
|
|
|
456 |
#undef wdev
|
|
|
457 |
#define wdev ((gx_device_win_pr2 *)pdev)
|
|
|
458 |
|
|
|
459 |
/********************************************************************************/
|
|
|
460 |
|
|
|
461 |
/* ------ Private definitions ------ */
|
|
|
462 |
|
|
|
463 |
|
|
|
464 |
/* new win_pr2_print_page routine */
|
|
|
465 |
|
|
|
466 |
/* Write BMP header to memory, then send bitmap to printer */
|
|
|
467 |
/* one scan line at a time */
|
|
|
468 |
private int
|
|
|
469 |
win_pr2_print_page(gx_device_printer * pdev, FILE * file)
|
|
|
470 |
{
|
|
|
471 |
int raster = gdev_prn_raster(pdev);
|
|
|
472 |
|
|
|
473 |
/* BMP scan lines are padded to 32 bits. */
|
|
|
474 |
ulong bmp_raster = raster + (-raster & 3);
|
|
|
475 |
ulong bmp_raster_multi;
|
|
|
476 |
int scan_lines, yslice, lines, i;
|
|
|
477 |
int width;
|
|
|
478 |
int depth = pdev->color_info.depth;
|
|
|
479 |
byte *row;
|
|
|
480 |
int y;
|
|
|
481 |
int code = 0; /* return code */
|
|
|
482 |
MSG msg;
|
|
|
483 |
char dlgtext[32];
|
|
|
484 |
HGLOBAL hrow;
|
|
|
485 |
int ratio = ((gx_device_win_pr2 *)pdev)->ratio;
|
|
|
486 |
|
|
|
487 |
struct bmi_s {
|
|
|
488 |
BITMAPINFOHEADER h;
|
|
|
489 |
RGBQUAD pal[256];
|
|
|
490 |
} bmi;
|
|
|
491 |
|
|
|
492 |
scan_lines = dev_print_scan_lines(pdev);
|
|
|
493 |
width = (int)(pdev->width - ((dev_l_margin(pdev) + dev_r_margin(pdev) -
|
|
|
494 |
dev_x_offset(pdev)) * pdev->x_pixels_per_inch));
|
|
|
495 |
|
|
|
496 |
yslice = 65535 / bmp_raster; /* max lines in 64k */
|
|
|
497 |
bmp_raster_multi = bmp_raster * yslice;
|
|
|
498 |
hrow = GlobalAlloc(0, bmp_raster_multi);
|
|
|
499 |
row = GlobalLock(hrow);
|
|
|
500 |
if (row == 0) /* can't allocate row buffer */
|
|
|
501 |
return_error(gs_error_VMerror);
|
|
|
502 |
|
|
|
503 |
/* Write the info header. */
|
|
|
504 |
|
|
|
505 |
bmi.h.biSize = sizeof(bmi.h);
|
|
|
506 |
bmi.h.biWidth = pdev->width; /* wdev->mdev.width; */
|
|
|
507 |
bmi.h.biHeight = yslice;
|
|
|
508 |
bmi.h.biPlanes = 1;
|
|
|
509 |
bmi.h.biBitCount = pdev->color_info.depth;
|
|
|
510 |
bmi.h.biCompression = 0;
|
|
|
511 |
bmi.h.biSizeImage = 0; /* default */
|
|
|
512 |
bmi.h.biXPelsPerMeter = 0; /* default */
|
|
|
513 |
bmi.h.biYPelsPerMeter = 0; /* default */
|
|
|
514 |
|
|
|
515 |
StartPage(wdev->hdcprn);
|
|
|
516 |
|
|
|
517 |
/* Write the palette. */
|
|
|
518 |
|
|
|
519 |
if (depth <= 8) {
|
|
|
520 |
int i;
|
|
|
521 |
gx_color_value rgb[3];
|
|
|
522 |
LPRGBQUAD pq;
|
|
|
523 |
|
|
|
524 |
bmi.h.biClrUsed = 1 << depth;
|
|
|
525 |
bmi.h.biClrImportant = 1 << depth;
|
|
|
526 |
for (i = 0; i != 1 << depth; i++) {
|
|
|
527 |
(*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
|
|
|
528 |
(gx_color_index) i, rgb);
|
|
|
529 |
pq = &bmi.pal[i];
|
|
|
530 |
pq->rgbRed = gx_color_value_to_byte(rgb[0]);
|
|
|
531 |
pq->rgbGreen = gx_color_value_to_byte(rgb[1]);
|
|
|
532 |
pq->rgbBlue = gx_color_value_to_byte(rgb[2]);
|
|
|
533 |
pq->rgbReserved = 0;
|
|
|
534 |
}
|
|
|
535 |
} else {
|
|
|
536 |
bmi.h.biClrUsed = 0;
|
|
|
537 |
bmi.h.biClrImportant = 0;
|
|
|
538 |
}
|
|
|
539 |
|
|
|
540 |
if (!wdev->nocancel) {
|
|
|
541 |
sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
|
|
|
542 |
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext);
|
|
|
543 |
ShowWindow(wdev->hDlgModeless, SW_SHOW);
|
|
|
544 |
}
|
|
|
545 |
for (y = 0; y < scan_lines;) {
|
|
|
546 |
/* copy slice to row buffer */
|
|
|
547 |
if (y > scan_lines - yslice)
|
|
|
548 |
lines = scan_lines - y;
|
|
|
549 |
else
|
|
|
550 |
lines = yslice;
|
|
|
551 |
for (i = 0; i < lines; i++)
|
|
|
552 |
gdev_prn_copy_scan_lines(pdev, y + i,
|
|
|
553 |
row + (bmp_raster * (lines - 1 - i)), raster);
|
|
|
554 |
|
|
|
555 |
if (ratio > 1) {
|
|
|
556 |
StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio,
|
|
|
557 |
0, 0, pdev->width, lines,
|
|
|
558 |
row,
|
|
|
559 |
(BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY);
|
|
|
560 |
} else {
|
|
|
561 |
SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines,
|
|
|
562 |
0, 0, 0, lines,
|
|
|
563 |
row,
|
|
|
564 |
(BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS);
|
|
|
565 |
}
|
|
|
566 |
y += lines;
|
|
|
567 |
|
|
|
568 |
if (!wdev->nocancel) {
|
|
|
569 |
/* inform user of progress */
|
|
|
570 |
sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
|
|
|
571 |
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext);
|
|
|
572 |
}
|
|
|
573 |
/* process message loop */
|
|
|
574 |
while (PeekMessage(&msg, wdev->hDlgModeless, 0, 0, PM_REMOVE)) {
|
|
|
575 |
if ((wdev->hDlgModeless == 0) || !IsDialogMessage(wdev->hDlgModeless, &msg)) {
|
|
|
576 |
TranslateMessage(&msg);
|
|
|
577 |
DispatchMessage(&msg);
|
|
|
578 |
}
|
|
|
579 |
}
|
|
|
580 |
if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) {
|
|
|
581 |
/* user pressed cancel button */
|
|
|
582 |
break;
|
|
|
583 |
}
|
|
|
584 |
}
|
|
|
585 |
|
|
|
586 |
if ((!wdev->nocancel) && (wdev->hDlgModeless == 0))
|
|
|
587 |
code = gs_error_Fatal; /* exit Ghostscript cleanly */
|
|
|
588 |
else {
|
|
|
589 |
/* push out the page */
|
|
|
590 |
if (!wdev->nocancel)
|
|
|
591 |
SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE),
|
|
|
592 |
"Ejecting page...");
|
|
|
593 |
EndPage(wdev->hdcprn);
|
|
|
594 |
if (!wdev->nocancel)
|
|
|
595 |
ShowWindow(wdev->hDlgModeless, SW_HIDE);
|
|
|
596 |
}
|
|
|
597 |
|
|
|
598 |
GlobalUnlock(hrow);
|
|
|
599 |
GlobalFree(hrow);
|
|
|
600 |
|
|
|
601 |
return code;
|
|
|
602 |
}
|
|
|
603 |
|
|
|
604 |
/* combined color mappers */
|
|
|
605 |
|
|
|
606 |
/* 24-bit color mappers (taken from gdevmem2.c). */
|
|
|
607 |
/* Note that Windows expects RGB values in the order B,G,R. */
|
|
|
608 |
|
|
|
609 |
/* Map a r-g-b color to a color index. */
|
|
|
610 |
private gx_color_index
|
|
|
611 |
win_pr2_map_rgb_color(gx_device * dev, const gx_color_value cv[])
|
|
|
612 |
{
|
|
|
613 |
gx_color_value r = cv[0];
|
|
|
614 |
gx_color_value g = cv[1];
|
|
|
615 |
gx_color_value b = cv[2];
|
|
|
616 |
switch (dev->color_info.depth) {
|
|
|
617 |
case 1:
|
|
|
618 |
return gdev_prn_map_rgb_color(dev, cv);
|
|
|
619 |
case 4:
|
|
|
620 |
/* use only 8 colors */
|
|
|
621 |
return (r > (gx_max_color_value / 2 + 1) ? 4 : 0) +
|
|
|
622 |
(g > (gx_max_color_value / 2 + 1) ? 2 : 0) +
|
|
|
623 |
(b > (gx_max_color_value / 2 + 1) ? 1 : 0);
|
|
|
624 |
case 8:
|
|
|
625 |
return pc_8bit_map_rgb_color(dev, cv);
|
|
|
626 |
case 24:
|
|
|
627 |
return gx_color_value_to_byte(r) +
|
|
|
628 |
((uint) gx_color_value_to_byte(g) << 8) +
|
|
|
629 |
((ulong) gx_color_value_to_byte(b) << 16);
|
|
|
630 |
}
|
|
|
631 |
return 0; /* error */
|
|
|
632 |
}
|
|
|
633 |
|
|
|
634 |
/* Map a color index to a r-g-b color. */
|
|
|
635 |
private int
|
|
|
636 |
win_pr2_map_color_rgb(gx_device * dev, gx_color_index color,
|
|
|
637 |
gx_color_value prgb[3])
|
|
|
638 |
{
|
|
|
639 |
switch (dev->color_info.depth) {
|
|
|
640 |
case 1:
|
|
|
641 |
gdev_prn_map_color_rgb(dev, color, prgb);
|
|
|
642 |
break;
|
|
|
643 |
case 4:
|
|
|
644 |
/* use only 8 colors */
|
|
|
645 |
prgb[0] = (color & 4) ? gx_max_color_value : 0;
|
|
|
646 |
prgb[1] = (color & 2) ? gx_max_color_value : 0;
|
|
|
647 |
prgb[2] = (color & 1) ? gx_max_color_value : 0;
|
|
|
648 |
break;
|
|
|
649 |
case 8:
|
|
|
650 |
pc_8bit_map_color_rgb(dev, color, prgb);
|
|
|
651 |
break;
|
|
|
652 |
case 24:
|
|
|
653 |
prgb[2] = gx_color_value_from_byte(color >> 16);
|
|
|
654 |
prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
|
|
|
655 |
prgb[0] = gx_color_value_from_byte(color & 0xff);
|
|
|
656 |
break;
|
|
|
657 |
}
|
|
|
658 |
return 0;
|
|
|
659 |
}
|
|
|
660 |
|
|
|
661 |
void
|
|
|
662 |
win_pr2_set_bpp(gx_device * dev, int depth)
|
|
|
663 |
{
|
|
|
664 |
if (depth > 8) {
|
|
|
665 |
static const gx_device_color_info win_pr2_24color = dci_std_color(24);
|
|
|
666 |
|
|
|
667 |
dev->color_info = win_pr2_24color;
|
|
|
668 |
depth = 24;
|
|
|
669 |
} else if (depth >= 8) {
|
|
|
670 |
/* 8-bit (SuperVGA-style) color. */
|
|
|
671 |
/* (Uses a fixed palette of 3,3,2 bits.) */
|
|
|
672 |
static const gx_device_color_info win_pr2_8color = dci_pc_8bit;
|
|
|
673 |
|
|
|
674 |
dev->color_info = win_pr2_8color;
|
|
|
675 |
depth = 8;
|
|
|
676 |
} else if (depth >= 3) {
|
|
|
677 |
/* 3 plane printer */
|
|
|
678 |
/* suitable for impact dot matrix CMYK printers */
|
|
|
679 |
/* create 4-bit bitmap, but only use 8 colors */
|
|
|
680 |
static const gx_device_color_info win_pr2_4color = dci_values(3, 4, 1, 1, 2, 2);
|
|
|
681 |
|
|
|
682 |
dev->color_info = win_pr2_4color;
|
|
|
683 |
depth = 4;
|
|
|
684 |
} else { /* default is black_and_white */
|
|
|
685 |
static const gx_device_color_info win_pr2_1color = dci_std_color(1);
|
|
|
686 |
|
|
|
687 |
dev->color_info = win_pr2_1color;
|
|
|
688 |
depth = 1;
|
|
|
689 |
}
|
|
|
690 |
|
|
|
691 |
((gx_device_win_pr2 *)dev)->selected_bpp = depth;
|
|
|
692 |
|
|
|
693 |
/* copy encode/decode procedures */
|
|
|
694 |
dev->procs.encode_color = dev->procs.map_rgb_color;
|
|
|
695 |
dev->procs.decode_color = dev->procs.map_color_rgb;
|
|
|
696 |
if (depth == 1) {
|
|
|
697 |
dev->procs.get_color_mapping_procs =
|
|
|
698 |
gx_default_DevGray_get_color_mapping_procs;
|
|
|
699 |
dev->procs.get_color_comp_index =
|
|
|
700 |
gx_default_DevGray_get_color_comp_index;
|
|
|
701 |
}
|
|
|
702 |
else {
|
|
|
703 |
dev->procs.get_color_mapping_procs =
|
|
|
704 |
gx_default_DevRGB_get_color_mapping_procs;
|
|
|
705 |
dev->procs.get_color_comp_index =
|
|
|
706 |
gx_default_DevRGB_get_color_comp_index;
|
|
|
707 |
}
|
|
|
708 |
}
|
|
|
709 |
|
|
|
710 |
/********************************************************************************/
|
|
|
711 |
|
|
|
712 |
/* Get device parameters */
|
|
|
713 |
int
|
|
|
714 |
win_pr2_get_params(gx_device * pdev, gs_param_list * plist)
|
|
|
715 |
{
|
|
|
716 |
int code = gdev_prn_get_params(pdev, plist);
|
|
|
717 |
|
|
|
718 |
win_pr2_copy_check(wdev);
|
|
|
719 |
|
|
|
720 |
if (code >= 0)
|
|
|
721 |
code = param_write_bool(plist, "NoCancel",
|
|
|
722 |
&(wdev->nocancel));
|
|
|
723 |
if (code >= 0)
|
|
|
724 |
code = param_write_int(plist, "QueryUser",
|
|
|
725 |
&(wdev->query_user));
|
|
|
726 |
if (code >= 0)
|
|
|
727 |
code = win_pr2_write_user_settings(wdev, plist);
|
|
|
728 |
|
|
|
729 |
if ((code >= 0) && (wdev->Duplex_set > 0))
|
|
|
730 |
code = param_write_bool(plist, "Tumble",
|
|
|
731 |
&(wdev->tumble));
|
|
|
732 |
|
|
|
733 |
return code;
|
|
|
734 |
}
|
|
|
735 |
|
|
|
736 |
|
|
|
737 |
/* We implement this ourselves so that we can change BitsPerPixel */
|
|
|
738 |
/* before the device is opened */
|
|
|
739 |
int
|
|
|
740 |
win_pr2_put_params(gx_device * pdev, gs_param_list * plist)
|
|
|
741 |
{
|
|
|
742 |
int ecode = 0, code;
|
|
|
743 |
int old_bpp = pdev->color_info.depth;
|
|
|
744 |
int bpp = old_bpp;
|
|
|
745 |
bool tumble = wdev->tumble;
|
|
|
746 |
bool nocancel = wdev->nocancel;
|
|
|
747 |
int queryuser = 0;
|
|
|
748 |
bool old_duplex = wdev->Duplex;
|
|
|
749 |
bool old_tumble = wdev->tumble;
|
|
|
750 |
int old_orient = wdev->user_orient;
|
|
|
751 |
int old_color = wdev->user_color;
|
|
|
752 |
int old_paper = wdev->user_paper;
|
|
|
753 |
int old_mx_dpi = wdev->max_dpi;
|
|
|
754 |
|
|
|
755 |
if (wdev->Duplex_set < 0) {
|
|
|
756 |
wdev->Duplex_set = 0;
|
|
|
757 |
wdev->Duplex = false;
|
|
|
758 |
wdev->tumble = false;
|
|
|
759 |
}
|
|
|
760 |
|
|
|
761 |
win_pr2_copy_check(wdev);
|
|
|
762 |
|
|
|
763 |
code = win_pr2_read_user_settings(wdev, plist);
|
|
|
764 |
|
|
|
765 |
switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
|
|
|
766 |
case 0:
|
|
|
767 |
if (pdev->is_open) {
|
|
|
768 |
if (wdev->selected_bpp == bpp) {
|
|
|
769 |
break;
|
|
|
770 |
}
|
|
|
771 |
ecode = gs_error_rangecheck;
|
|
|
772 |
} else { /* change dev->color_info is valid before device is opened */
|
|
|
773 |
win_pr2_set_bpp(pdev, bpp);
|
|
|
774 |
break;
|
|
|
775 |
}
|
|
|
776 |
goto bppe;
|
|
|
777 |
default:
|
|
|
778 |
ecode = code;
|
|
|
779 |
bppe:param_signal_error(plist, "BitsPerPixel", ecode);
|
|
|
780 |
case 1:
|
|
|
781 |
break;
|
|
|
782 |
}
|
|
|
783 |
|
|
|
784 |
switch (code = param_read_bool(plist, "NoCancel", &nocancel)) {
|
|
|
785 |
case 0:
|
|
|
786 |
if (pdev->is_open) {
|
|
|
787 |
if (wdev->nocancel == nocancel) {
|
|
|
788 |
break;
|
|
|
789 |
}
|
|
|
790 |
ecode = gs_error_rangecheck;
|
|
|
791 |
} else {
|
|
|
792 |
wdev->nocancel = nocancel;
|
|
|
793 |
break;
|
|
|
794 |
}
|
|
|
795 |
goto nocancele;
|
|
|
796 |
default:
|
|
|
797 |
ecode = code;
|
|
|
798 |
nocancele:param_signal_error(plist, "NoCancel", ecode);
|
|
|
799 |
case 1:
|
|
|
800 |
break;
|
|
|
801 |
}
|
|
|
802 |
|
|
|
803 |
switch (code = param_read_bool(plist, "Tumble", &tumble)) {
|
|
|
804 |
case 0:
|
|
|
805 |
wdev->tumble = tumble;
|
|
|
806 |
break;
|
|
|
807 |
default:
|
|
|
808 |
ecode = code;
|
|
|
809 |
param_signal_error(plist, "Tumble", ecode);
|
|
|
810 |
case 1:
|
|
|
811 |
break;
|
|
|
812 |
}
|
|
|
813 |
|
|
|
814 |
switch (code = param_read_int(plist, "QueryUser", &queryuser)) {
|
|
|
815 |
case 0:
|
|
|
816 |
if ((queryuser > 0) &&
|
|
|
817 |
(queryuser < 4)) {
|
|
|
818 |
win_pr2_print_setup_interaction(wdev, queryuser);
|
|
|
819 |
}
|
|
|
820 |
break;
|
|
|
821 |
default:
|
|
|
822 |
ecode = code;
|
|
|
823 |
param_signal_error(plist, "QueryUser", ecode);
|
|
|
824 |
case 1:
|
|
|
825 |
break;
|
|
|
826 |
}
|
|
|
827 |
|
|
|
828 |
if (ecode >= 0)
|
|
|
829 |
ecode = gdev_prn_put_params(pdev, plist);
|
|
|
830 |
|
|
|
831 |
if (wdev->win32_hdevmode && wdev->hdcprn) {
|
|
|
832 |
if ( (old_duplex != wdev->Duplex)
|
|
|
833 |
|| (old_tumble != wdev->tumble)
|
|
|
834 |
|| (old_orient != wdev->user_orient)
|
|
|
835 |
|| (old_color != wdev->user_color)
|
|
|
836 |
|| (old_paper != wdev->user_paper)
|
|
|
837 |
|| (old_mx_dpi != wdev->max_dpi) ) {
|
|
|
838 |
|
|
|
839 |
LPDEVMODE pdevmode = GlobalLock(wdev->win32_hdevmode);
|
|
|
840 |
|
|
|
841 |
if (pdevmode) {
|
|
|
842 |
win_pr2_update_win(wdev, pdevmode);
|
|
|
843 |
ResetDC(wdev->hdcprn, pdevmode);
|
|
|
844 |
GlobalUnlock(pdevmode);
|
|
|
845 |
}
|
|
|
846 |
}
|
|
|
847 |
}
|
|
|
848 |
|
|
|
849 |
return ecode;
|
|
|
850 |
}
|
|
|
851 |
|
|
|
852 |
#undef wdev
|
|
|
853 |
|
|
|
854 |
/********************************************************************************/
|
|
|
855 |
|
|
|
856 |
|
|
|
857 |
/* Get Device Context for printer */
|
|
|
858 |
private int
|
|
|
859 |
win_pr2_getdc(gx_device_win_pr2 * wdev)
|
|
|
860 |
{
|
|
|
861 |
char *device;
|
|
|
862 |
char *devices;
|
|
|
863 |
char *p;
|
|
|
864 |
char driverbuf[512];
|
|
|
865 |
char *driver;
|
|
|
866 |
char *output;
|
|
|
867 |
char *devcap;
|
|
|
868 |
int devcapsize;
|
|
|
869 |
int size;
|
|
|
870 |
|
|
|
871 |
int i, n;
|
|
|
872 |
POINT *pp;
|
|
|
873 |
int paperindex;
|
|
|
874 |
int paperwidth, paperheight;
|
|
|
875 |
int orientation;
|
|
|
876 |
int papersize;
|
|
|
877 |
char papername[64];
|
|
|
878 |
char drvname[32];
|
|
|
879 |
HINSTANCE hlib;
|
|
|
880 |
LPFNDEVMODE pfnExtDeviceMode;
|
|
|
881 |
LPFNDEVCAPS pfnDeviceCapabilities;
|
|
|
882 |
LPDEVMODE podevmode, pidevmode;
|
|
|
883 |
|
|
|
884 |
HANDLE hprinter;
|
|
|
885 |
|
|
|
886 |
/* first try to derive the printer name from -sOutputFile= */
|
|
|
887 |
/* is printer if name prefixed by \\spool\ or by %printer% */
|
|
|
888 |
if (is_spool(wdev->fname)) {
|
|
|
889 |
device = wdev->fname + 8; /* skip over \\spool\ */
|
|
|
890 |
wdev->use_old_spool_name = true;
|
|
|
891 |
} else if (strncmp("%printer%",wdev->fname,9) == 0) {
|
|
|
892 |
device = wdev->fname + 9; /* skip over %printer% */
|
|
|
893 |
wdev->use_old_spool_name = false;
|
|
|
894 |
} else {
|
|
|
895 |
return FALSE;
|
|
|
896 |
}
|
|
|
897 |
|
|
|
898 |
/* now try to match the printer name against the [Devices] section */
|
|
|
899 |
if ((devices = gs_malloc(wdev->memory, 4096, 1, "win_pr2_getdc")) == (char *)NULL)
|
|
|
900 |
return FALSE;
|
|
|
901 |
GetProfileString("Devices", NULL, "", devices, 4096);
|
|
|
902 |
p = devices;
|
|
|
903 |
while (*p) {
|
|
|
904 |
if (stricmp(p, device) == 0)
|
|
|
905 |
break;
|
|
|
906 |
p += strlen(p) + 1;
|
|
|
907 |
}
|
|
|
908 |
if (*p == '\0')
|
|
|
909 |
p = NULL;
|
|
|
910 |
gs_free(wdev->memory, devices, 4096, 1, "win_pr2_getdc");
|
|
|
911 |
if (p == NULL)
|
|
|
912 |
return FALSE; /* doesn't match an available printer */
|
|
|
913 |
|
|
|
914 |
/* the printer exists, get the remaining information from win.ini */
|
|
|
915 |
GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
|
|
|
916 |
driver = strtok(driverbuf, ",");
|
|
|
917 |
output = strtok(NULL, ",");
|
|
|
918 |
if (is_win32s)
|
|
|
919 |
{
|
|
|
920 |
strcpy(drvname, driver);
|
|
|
921 |
strcat(drvname, ".drv");
|
|
|
922 |
driver = drvname;
|
|
|
923 |
}
|
|
|
924 |
|
|
|
925 |
if (!is_win32s) { /* Win32 */
|
|
|
926 |
if (!OpenPrinter(device, &hprinter, NULL))
|
|
|
927 |
return FALSE;
|
|
|
928 |
size = DocumentProperties(NULL, hprinter, device, NULL, NULL, 0);
|
|
|
929 |
if ((podevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
|
|
|
930 |
ClosePrinter(hprinter);
|
|
|
931 |
return FALSE;
|
|
|
932 |
}
|
|
|
933 |
if ((pidevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
|
|
|
934 |
gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
|
|
|
935 |
ClosePrinter(hprinter);
|
|
|
936 |
return FALSE;
|
|
|
937 |
}
|
|
|
938 |
DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);
|
|
|
939 |
pfnDeviceCapabilities = (LPFNDEVCAPS) DeviceCapabilities;
|
|
|
940 |
} else
|
|
|
941 |
{ /* Win16 and Win32s */
|
|
|
942 |
/* now load the printer driver */
|
|
|
943 |
hlib = LoadLibrary(driver);
|
|
|
944 |
if (hlib < (HINSTANCE) HINSTANCE_ERROR)
|
|
|
945 |
return FALSE;
|
|
|
946 |
|
|
|
947 |
/* call ExtDeviceMode() to get default parameters */
|
|
|
948 |
pfnExtDeviceMode = (LPFNDEVMODE) GetProcAddress(hlib, "ExtDeviceMode");
|
|
|
949 |
if (pfnExtDeviceMode == (LPFNDEVMODE) NULL) {
|
|
|
950 |
FreeLibrary(hlib);
|
|
|
951 |
return FALSE;
|
|
|
952 |
}
|
|
|
953 |
pfnDeviceCapabilities = (LPFNDEVCAPS) GetProcAddress(hlib, "DeviceCapabilities");
|
|
|
954 |
if (pfnDeviceCapabilities == (LPFNDEVCAPS) NULL) {
|
|
|
955 |
FreeLibrary(hlib);
|
|
|
956 |
return FALSE;
|
|
|
957 |
}
|
|
|
958 |
size = pfnExtDeviceMode(NULL, hlib, NULL, device, output, NULL, NULL, 0);
|
|
|
959 |
if ((podevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
|
|
|
960 |
FreeLibrary(hlib);
|
|
|
961 |
return FALSE;
|
|
|
962 |
}
|
|
|
963 |
if ((pidevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
|
|
|
964 |
gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
|
|
|
965 |
FreeLibrary(hlib);
|
|
|
966 |
return FALSE;
|
|
|
967 |
}
|
|
|
968 |
pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
|
|
|
969 |
NULL, NULL, DM_OUT_BUFFER);
|
|
|
970 |
}
|
|
|
971 |
|
|
|
972 |
/* now find out what paper sizes are available */
|
|
|
973 |
devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL);
|
|
|
974 |
devcapsize *= sizeof(POINT);
|
|
|
975 |
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
|
|
|
976 |
return FALSE;
|
|
|
977 |
n = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL);
|
|
|
978 |
paperwidth = (int)(wdev->MediaSize[0] * 254 / 72);
|
|
|
979 |
paperheight = (int)(wdev->MediaSize[1] * 254 / 72);
|
|
|
980 |
papername[0] = '\0';
|
|
|
981 |
papersize = 0;
|
|
|
982 |
paperindex = -1;
|
|
|
983 |
orientation = 0;
|
|
|
984 |
pp = (POINT *) devcap;
|
|
|
985 |
for (i = 0; i < n; i++, pp++) {
|
|
|
986 |
if ((pp->x < paperwidth + 20) && (pp->x > paperwidth - 20) &&
|
|
|
987 |
(pp->y < paperheight + 20) && (pp->y > paperheight - 20)) {
|
|
|
988 |
paperindex = i;
|
|
|
989 |
paperwidth = pp->x;
|
|
|
990 |
paperheight = pp->y;
|
|
|
991 |
orientation = DMORIENT_PORTRAIT;
|
|
|
992 |
break;
|
|
|
993 |
}
|
|
|
994 |
}
|
|
|
995 |
if (paperindex < 0) {
|
|
|
996 |
/* try again in landscape */
|
|
|
997 |
pp = (POINT *) devcap;
|
|
|
998 |
for (i = 0; i < n; i++, pp++) {
|
|
|
999 |
if ((pp->x < paperheight + 20) && (pp->x > paperheight - 20) &&
|
|
|
1000 |
(pp->y < paperwidth + 20) && (pp->y > paperwidth - 20)) {
|
|
|
1001 |
paperindex = i;
|
|
|
1002 |
paperwidth = pp->x;
|
|
|
1003 |
paperheight = pp->y;
|
|
|
1004 |
orientation = DMORIENT_LANDSCAPE;
|
|
|
1005 |
break;
|
|
|
1006 |
}
|
|
|
1007 |
}
|
|
|
1008 |
}
|
|
|
1009 |
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
|
|
|
1010 |
|
|
|
1011 |
/* get the dmPaperSize */
|
|
|
1012 |
devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERS, NULL, NULL);
|
|
|
1013 |
devcapsize *= sizeof(WORD);
|
|
|
1014 |
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
|
|
|
1015 |
return FALSE;
|
|
|
1016 |
n = pfnDeviceCapabilities(device, output, DC_PAPERS, devcap, NULL);
|
|
|
1017 |
if ((paperindex >= 0) && (paperindex < n))
|
|
|
1018 |
papersize = ((WORD *) devcap)[paperindex];
|
|
|
1019 |
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
|
|
|
1020 |
|
|
|
1021 |
/* get the paper name */
|
|
|
1022 |
devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
|
|
|
1023 |
devcapsize *= 64;
|
|
|
1024 |
if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
|
|
|
1025 |
return FALSE;
|
|
|
1026 |
n = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL);
|
|
|
1027 |
if ((paperindex >= 0) && (paperindex < n))
|
|
|
1028 |
strcpy(papername, devcap + paperindex * 64);
|
|
|
1029 |
gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
|
|
|
1030 |
|
|
|
1031 |
memcpy(pidevmode, podevmode, size);
|
|
|
1032 |
|
|
|
1033 |
pidevmode->dmFields = 0;
|
|
|
1034 |
|
|
|
1035 |
wdev->paper_name[0] = 0;
|
|
|
1036 |
|
|
|
1037 |
if ( (wdev->user_paper)
|
|
|
1038 |
&& (wdev->user_paper != papersize) ) {
|
|
|
1039 |
papersize = wdev->user_paper;
|
|
|
1040 |
paperheight = 0;
|
|
|
1041 |
paperwidth = 0;
|
|
|
1042 |
papername[0] = 0;
|
|
|
1043 |
}
|
|
|
1044 |
if (wdev->user_orient) {
|
|
|
1045 |
orientation = wdev->user_orient;
|
|
|
1046 |
}
|
|
|
1047 |
|
|
|
1048 |
pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
|
|
|
1049 |
pidevmode->dmFields |= DM_DEFAULTSOURCE;
|
|
|
1050 |
pidevmode->dmDefaultSource = 0;
|
|
|
1051 |
|
|
|
1052 |
if (orientation) {
|
|
|
1053 |
wdev->user_orient = orientation;
|
|
|
1054 |
}
|
|
|
1055 |
if (papersize) {
|
|
|
1056 |
wdev->user_paper = papersize;
|
|
|
1057 |
strcpy (wdev->paper_name, papername);
|
|
|
1058 |
}
|
|
|
1059 |
|
|
|
1060 |
if (paperheight && paperwidth) {
|
|
|
1061 |
pidevmode->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
|
|
|
1062 |
pidevmode->dmPaperWidth = paperwidth;
|
|
|
1063 |
pidevmode->dmPaperLength = paperheight;
|
|
|
1064 |
wdev->user_media_size[0] = paperwidth / 254.0 * 72.0;
|
|
|
1065 |
wdev->user_media_size[1] = paperheight / 254.0 * 72.0;
|
|
|
1066 |
}
|
|
|
1067 |
|
|
|
1068 |
if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
|
|
|
1069 |
wdev->Duplex_set = 1;
|
|
|
1070 |
}
|
|
|
1071 |
|
|
|
1072 |
win_pr2_update_win(wdev, pidevmode);
|
|
|
1073 |
|
|
|
1074 |
if (!is_win32s) {
|
|
|
1075 |
|
|
|
1076 |
/* merge the entries */
|
|
|
1077 |
DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
|
|
|
1078 |
ClosePrinter(hprinter);
|
|
|
1079 |
|
|
|
1080 |
/* now get a DC */
|
|
|
1081 |
wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
|
|
|
1082 |
} else
|
|
|
1083 |
{ /* Win16 and Win32s */
|
|
|
1084 |
pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
|
|
|
1085 |
pidevmode, NULL, DM_IN_BUFFER | DM_OUT_BUFFER);
|
|
|
1086 |
/* release the printer driver */
|
|
|
1087 |
FreeLibrary(hlib);
|
|
|
1088 |
/* now get a DC */
|
|
|
1089 |
if (is_win32s)
|
|
|
1090 |
strtok(driver, "."); /* remove .drv */
|
|
|
1091 |
wdev->hdcprn = CreateDC(driver, device, output, podevmode);
|
|
|
1092 |
}
|
|
|
1093 |
|
|
|
1094 |
if (wdev->win32_hdevmode == NULL) {
|
|
|
1095 |
wdev->win32_hdevmode = GlobalAlloc(0, sizeof(DEVMODE));
|
|
|
1096 |
}
|
|
|
1097 |
|
|
|
1098 |
if (wdev->win32_hdevmode) {
|
|
|
1099 |
LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
|
|
|
1100 |
if (pdevmode) {
|
|
|
1101 |
memcpy(pdevmode, podevmode, sizeof(DEVMODE));
|
|
|
1102 |
GlobalUnlock(wdev->win32_hdevmode);
|
|
|
1103 |
}
|
|
|
1104 |
}
|
|
|
1105 |
|
|
|
1106 |
gs_free(wdev->memory, pidevmode, size, 1, "win_pr2_getdc");
|
|
|
1107 |
gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
|
|
|
1108 |
|
|
|
1109 |
if (wdev->hdcprn != (HDC) NULL)
|
|
|
1110 |
return TRUE; /* success */
|
|
|
1111 |
|
|
|
1112 |
/* fall back to prompting user */
|
|
|
1113 |
return FALSE;
|
|
|
1114 |
}
|
|
|
1115 |
|
|
|
1116 |
|
|
|
1117 |
/*
|
|
|
1118 |
* Minimalist update of the wdev parameters (mainly for the
|
|
|
1119 |
* UserSettings parameters).
|
|
|
1120 |
*/
|
|
|
1121 |
|
|
|
1122 |
private int
|
|
|
1123 |
win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
|
|
|
1124 |
{
|
|
|
1125 |
if (pdevmode == 0)
|
|
|
1126 |
return FALSE;
|
|
|
1127 |
|
|
|
1128 |
if (pdevmode->dmFields & DM_COLOR) {
|
|
|
1129 |
dev->user_color = pdevmode->dmColor;
|
|
|
1130 |
}
|
|
|
1131 |
if (pdevmode->dmFields & DM_ORIENTATION) {
|
|
|
1132 |
dev->user_orient = pdevmode->dmOrientation;
|
|
|
1133 |
}
|
|
|
1134 |
if (pdevmode->dmFields & DM_PAPERSIZE) {
|
|
|
1135 |
dev->user_paper = pdevmode->dmPaperSize;
|
|
|
1136 |
dev->user_media_size[0] = pdevmode->dmPaperWidth / 254.0 * 72.0;
|
|
|
1137 |
dev->user_media_size[1] = pdevmode->dmPaperLength / 254.0 * 72.0;
|
|
|
1138 |
dev->paper_name[0] = 0; /* unknown paper size */
|
|
|
1139 |
}
|
|
|
1140 |
if (pdevmode->dmFields & DM_DUPLEX) {
|
|
|
1141 |
dev->Duplex_set = 1;
|
|
|
1142 |
dev->Duplex = pdevmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
|
|
|
1143 |
dev->tumble = pdevmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
|
|
|
1144 |
}
|
|
|
1145 |
|
|
|
1146 |
return TRUE;
|
|
|
1147 |
}
|
|
|
1148 |
|
|
|
1149 |
private int
|
|
|
1150 |
win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
|
|
|
1151 |
{
|
|
|
1152 |
if (dev->Duplex_set > 0) {
|
|
|
1153 |
pdevmode->dmFields |= DM_DUPLEX;
|
|
|
1154 |
pdevmode->dmDuplex = DMDUP_SIMPLEX;
|
|
|
1155 |
if (dev->Duplex) {
|
|
|
1156 |
if (dev->tumble == false) {
|
|
|
1157 |
pdevmode->dmDuplex = DMDUP_VERTICAL;
|
|
|
1158 |
} else {
|
|
|
1159 |
pdevmode->dmDuplex = DMDUP_HORIZONTAL;
|
|
|
1160 |
}
|
|
|
1161 |
}
|
|
|
1162 |
}
|
|
|
1163 |
|
|
|
1164 |
if (dev->user_color) {
|
|
|
1165 |
pdevmode->dmColor = dev->user_color;
|
|
|
1166 |
pdevmode->dmFields |= DM_COLOR;
|
|
|
1167 |
}
|
|
|
1168 |
|
|
|
1169 |
if (dev->user_orient) {
|
|
|
1170 |
pdevmode->dmFields |= DM_ORIENTATION;
|
|
|
1171 |
pdevmode->dmOrientation = dev->user_orient;
|
|
|
1172 |
}
|
|
|
1173 |
|
|
|
1174 |
if (dev->user_paper) {
|
|
|
1175 |
pdevmode->dmFields |= DM_PAPERSIZE;
|
|
|
1176 |
pdevmode->dmPaperSize = dev->user_paper;
|
|
|
1177 |
}
|
|
|
1178 |
return 0;
|
|
|
1179 |
}
|
|
|
1180 |
|
|
|
1181 |
/********************************************************************************/
|
|
|
1182 |
|
|
|
1183 |
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
|
|
|
1184 |
switch ( code = pread(dict.list, (param_name = pname), &(pa)) )\
|
|
|
1185 |
{\
|
|
|
1186 |
case 0:\
|
|
|
1187 |
if ( (pa).size != psize )\
|
|
|
1188 |
ecode = gs_note_error(gs_error_rangecheck);\
|
|
|
1189 |
else {
|
|
|
1190 |
/* The body of the processing code goes here. */
|
|
|
1191 |
/* If it succeeds, it should do a 'break'; */
|
|
|
1192 |
/* if it fails, it should set ecode and fall through. */
|
|
|
1193 |
#define END_ARRAY_PARAM(pa, e)\
|
|
|
1194 |
}\
|
|
|
1195 |
goto e;\
|
|
|
1196 |
default:\
|
|
|
1197 |
ecode = code;\
|
|
|
1198 |
e: param_signal_error(dict.list, param_name, ecode);\
|
|
|
1199 |
case 1:\
|
|
|
1200 |
(pa).data = 0; /* mark as not filled */\
|
|
|
1201 |
}
|
|
|
1202 |
|
|
|
1203 |
|
|
|
1204 |
/* Put the user params from UserSettings into our */
|
|
|
1205 |
/* internal variables. */
|
|
|
1206 |
private int
|
|
|
1207 |
win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
|
|
|
1208 |
{
|
|
|
1209 |
gs_param_dict dict;
|
|
|
1210 |
gs_param_string docn = { 0 };
|
|
|
1211 |
const char* dict_name = "UserSettings";
|
|
|
1212 |
const char* param_name = "";
|
|
|
1213 |
int code = 0;
|
|
|
1214 |
int ecode = 0;
|
|
|
1215 |
|
|
|
1216 |
switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
|
|
|
1217 |
default:
|
|
|
1218 |
param_signal_error(plist, dict_name, code);
|
|
|
1219 |
return code;
|
|
|
1220 |
case 1:
|
|
|
1221 |
break;
|
|
|
1222 |
case 0:
|
|
|
1223 |
{
|
|
|
1224 |
gs_param_int_array ia;
|
|
|
1225 |
|
|
|
1226 |
BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
|
|
|
1227 |
if ((ia.data[0] < 0) ||
|
|
|
1228 |
(ia.data[1] < 0) ||
|
|
|
1229 |
(ia.data[0] > ia.data[1]))
|
|
|
1230 |
ecode = gs_note_error(gs_error_rangecheck);
|
|
|
1231 |
wdev->doc_page_begin = ia.data[0];
|
|
|
1232 |
wdev->doc_page_end = ia.data[1];
|
|
|
1233 |
END_ARRAY_PARAM(ia, doc_range_error)
|
|
|
1234 |
|
|
|
1235 |
BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
|
|
|
1236 |
if ((ia.data[0] < 0) ||
|
|
|
1237 |
(ia.data[1] < 0) ||
|
|
|
1238 |
(ia.data[0] > ia.data[1]))
|
|
|
1239 |
ecode = gs_note_error(gs_error_rangecheck);
|
|
|
1240 |
wdev->user_page_begin = ia.data[0];
|
|
|
1241 |
wdev->user_page_end = ia.data[1];
|
|
|
1242 |
END_ARRAY_PARAM(ia, sel_range_error)
|
|
|
1243 |
|
|
|
1244 |
param_read_int(dict.list, "Copies", &wdev->user_copies);
|
|
|
1245 |
param_read_int(dict.list, "Paper", &wdev->user_paper);
|
|
|
1246 |
param_read_int(dict.list, "Orientation", &wdev->user_orient);
|
|
|
1247 |
param_read_int(dict.list, "Color", &wdev->user_color);
|
|
|
1248 |
param_read_int(dict.list, "MaxResolution", &wdev->max_dpi);
|
|
|
1249 |
|
|
|
1250 |
switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
|
|
|
1251 |
case 0:
|
|
|
1252 |
if (docn.size < sizeof(wdev->doc_name))
|
|
|
1253 |
break;
|
|
|
1254 |
code = gs_error_rangecheck;
|
|
|
1255 |
/* fall through */
|
|
|
1256 |
default:
|
|
|
1257 |
ecode = code;
|
|
|
1258 |
param_signal_error(plist, param_name, ecode);
|
|
|
1259 |
/* fall through */
|
|
|
1260 |
case 1:
|
|
|
1261 |
docn.data = 0;
|
|
|
1262 |
break;
|
|
|
1263 |
}
|
|
|
1264 |
|
|
|
1265 |
param_end_read_dict(plist, dict_name, &dict);
|
|
|
1266 |
|
|
|
1267 |
if (docn.data) {
|
|
|
1268 |
memcpy(wdev->doc_name, docn.data, docn.size);
|
|
|
1269 |
wdev->doc_name[docn.size] = 0;
|
|
|
1270 |
}
|
|
|
1271 |
|
|
|
1272 |
wdev->print_copies = 1;
|
|
|
1273 |
|
|
|
1274 |
if (wdev->win32_hdevmode) {
|
|
|
1275 |
LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
|
|
|
1276 |
if (devmode) {
|
|
|
1277 |
devmode->dmCopies = wdev->user_copies;
|
|
|
1278 |
devmode->dmPaperSize = wdev->user_paper;
|
|
|
1279 |
devmode->dmOrientation = wdev->user_orient;
|
|
|
1280 |
devmode->dmColor = wdev->user_color;
|
|
|
1281 |
GlobalUnlock(wdev->win32_hdevmode);
|
|
|
1282 |
}
|
|
|
1283 |
}
|
|
|
1284 |
}
|
|
|
1285 |
break;
|
|
|
1286 |
}
|
|
|
1287 |
|
|
|
1288 |
return code;
|
|
|
1289 |
}
|
|
|
1290 |
|
|
|
1291 |
|
|
|
1292 |
private int
|
|
|
1293 |
win_pr2_write_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
|
|
|
1294 |
{
|
|
|
1295 |
gs_param_dict dict;
|
|
|
1296 |
gs_param_int_array range;
|
|
|
1297 |
gs_param_float_array box;
|
|
|
1298 |
gs_param_string docn;
|
|
|
1299 |
gs_param_string papn;
|
|
|
1300 |
int array[2];
|
|
|
1301 |
const char* pname = "UserSettings";
|
|
|
1302 |
int code;
|
|
|
1303 |
|
|
|
1304 |
dict.size = 12;
|
|
|
1305 |
code = param_begin_write_dict(plist, pname, &dict, false);
|
|
|
1306 |
if (code < 0) return code;
|
|
|
1307 |
|
|
|
1308 |
array[0] = wdev->doc_page_begin;
|
|
|
1309 |
array[1] = wdev->doc_page_end;
|
|
|
1310 |
range.data = array;
|
|
|
1311 |
range.size = 2;
|
|
|
1312 |
range.persistent = false;
|
|
|
1313 |
code = param_write_int_array(dict.list, "DocumentRange", &range);
|
|
|
1314 |
if (code < 0) goto error;
|
|
|
1315 |
|
|
|
1316 |
array[0] = wdev->user_page_begin;
|
|
|
1317 |
array[1] = wdev->user_page_end;
|
|
|
1318 |
range.data = array;
|
|
|
1319 |
range.size = 2;
|
|
|
1320 |
range.persistent = false;
|
|
|
1321 |
code = param_write_int_array(dict.list, "SelectedRange", &range);
|
|
|
1322 |
if (code < 0) goto error;
|
|
|
1323 |
|
|
|
1324 |
box.data = wdev->user_media_size;
|
|
|
1325 |
box.size = 2;
|
|
|
1326 |
box.persistent = false;
|
|
|
1327 |
code = param_write_float_array(dict.list, "MediaSize", &box);
|
|
|
1328 |
if (code < 0) goto error;
|
|
|
1329 |
|
|
|
1330 |
code = param_write_int(dict.list, "Copies", &wdev->user_copies);
|
|
|
1331 |
if (code < 0) goto error;
|
|
|
1332 |
|
|
|
1333 |
code = param_write_int(dict.list, "Paper", &wdev->user_paper);
|
|
|
1334 |
if (code < 0) goto error;
|
|
|
1335 |
|
|
|
1336 |
code = param_write_int(dict.list, "Orientation", &wdev->user_orient);
|
|
|
1337 |
if (code < 0) goto error;
|
|
|
1338 |
|
|
|
1339 |
code = param_write_int(dict.list, "Color", &wdev->user_color);
|
|
|
1340 |
if (code < 0) goto error;
|
|
|
1341 |
|
|
|
1342 |
code = param_write_int(dict.list, "MaxResolution", &wdev->max_dpi);
|
|
|
1343 |
if (code < 0) goto error;
|
|
|
1344 |
|
|
|
1345 |
code = param_write_int(dict.list, "PrintCopies", &wdev->print_copies);
|
|
|
1346 |
if (code < 0) goto error;
|
|
|
1347 |
|
|
|
1348 |
docn.data = (const byte*)wdev->doc_name;
|
|
|
1349 |
docn.size = strlen(wdev->doc_name);
|
|
|
1350 |
docn.persistent = false;
|
|
|
1351 |
|
|
|
1352 |
code = param_write_string(dict.list, "DocumentName", &docn);
|
|
|
1353 |
if (code < 0) goto error;
|
|
|
1354 |
|
|
|
1355 |
papn.data = (const byte*)wdev->paper_name;
|
|
|
1356 |
papn.size = strlen(wdev->paper_name);
|
|
|
1357 |
papn.persistent = false;
|
|
|
1358 |
|
|
|
1359 |
code = param_write_string(dict.list, "PaperName", &papn);
|
|
|
1360 |
if (code < 0) goto error;
|
|
|
1361 |
|
|
|
1362 |
code = param_write_bool(dict.list, "UserChangedSettings", &wdev->user_changed_settings);
|
|
|
1363 |
|
|
|
1364 |
error:
|
|
|
1365 |
param_end_write_dict(plist, pname, &dict);
|
|
|
1366 |
return code;
|
|
|
1367 |
}
|
|
|
1368 |
|
|
|
1369 |
/********************************************************************************/
|
|
|
1370 |
|
|
|
1371 |
/* Show up a dialog for the user to choose a printer and a paper size.
|
|
|
1372 |
* If mode == 3, then automatically select the default Windows printer
|
|
|
1373 |
* instead of asking the user.
|
|
|
1374 |
*/
|
|
|
1375 |
|
|
|
1376 |
private int
|
|
|
1377 |
win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode)
|
|
|
1378 |
{
|
|
|
1379 |
PRINTDLG pd;
|
|
|
1380 |
LPDEVMODE devmode;
|
|
|
1381 |
LPDEVNAMES devnames;
|
|
|
1382 |
|
|
|
1383 |
wdev->user_changed_settings = FALSE;
|
|
|
1384 |
wdev->query_user = mode;
|
|
|
1385 |
|
|
|
1386 |
memset(&pd, 0, sizeof(pd));
|
|
|
1387 |
pd.lStructSize = sizeof(pd);
|
|
|
1388 |
pd.hwndOwner = PARENT_WINDOW;
|
|
|
1389 |
|
|
|
1390 |
switch (mode) {
|
|
|
1391 |
case 2: pd.Flags = PD_PRINTSETUP; break;
|
|
|
1392 |
case 3: pd.Flags = PD_RETURNDEFAULT; break;
|
|
|
1393 |
default: pd.Flags = 0; break;
|
|
|
1394 |
}
|
|
|
1395 |
|
|
|
1396 |
pd.Flags |= PD_USEDEVMODECOPIES;
|
|
|
1397 |
|
|
|
1398 |
pd.nMinPage = wdev->doc_page_begin;
|
|
|
1399 |
pd.nMaxPage = wdev->doc_page_end;
|
|
|
1400 |
pd.nFromPage = wdev->user_page_begin;
|
|
|
1401 |
pd.nToPage = wdev->user_page_end;
|
|
|
1402 |
pd.nCopies = wdev->user_copies;
|
|
|
1403 |
|
|
|
1404 |
/* Show the Print Setup dialog and let the user choose a printer
|
|
|
1405 |
* and a paper size/orientation.
|
|
|
1406 |
*/
|
|
|
1407 |
|
|
|
1408 |
if (!PrintDlg(&pd)) return FALSE;
|
|
|
1409 |
|
|
|
1410 |
devmode = (LPDEVMODE) GlobalLock(pd.hDevMode);
|
|
|
1411 |
devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);
|
|
|
1412 |
|
|
|
1413 |
wdev->user_changed_settings = TRUE;
|
|
|
1414 |
if (wdev->use_old_spool_name) {
|
|
|
1415 |
sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
|
|
|
1416 |
} else {
|
|
|
1417 |
sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
|
|
|
1418 |
}
|
|
|
1419 |
|
|
|
1420 |
if (mode == 3) {
|
|
|
1421 |
devmode->dmCopies = wdev->user_copies * wdev->print_copies;
|
|
|
1422 |
pd.nCopies = 1;
|
|
|
1423 |
}
|
|
|
1424 |
|
|
|
1425 |
wdev->user_page_begin = pd.nFromPage;
|
|
|
1426 |
wdev->user_page_end = pd.nToPage;
|
|
|
1427 |
wdev->user_copies = devmode->dmCopies;
|
|
|
1428 |
wdev->print_copies = pd.nCopies;
|
|
|
1429 |
wdev->user_media_size[0] = devmode->dmPaperWidth / 254.0 * 72.0;
|
|
|
1430 |
wdev->user_media_size[1] = devmode->dmPaperLength / 254.0 * 72.0;
|
|
|
1431 |
wdev->user_paper = devmode->dmPaperSize;
|
|
|
1432 |
wdev->user_orient = devmode->dmOrientation;
|
|
|
1433 |
wdev->user_color = devmode->dmColor;
|
|
|
1434 |
|
|
|
1435 |
if (devmode->dmFields & DM_DUPLEX) {
|
|
|
1436 |
wdev->Duplex_set = 1;
|
|
|
1437 |
wdev->Duplex = devmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
|
|
|
1438 |
wdev->tumble = devmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
|
|
|
1439 |
}
|
|
|
1440 |
|
|
|
1441 |
{
|
|
|
1442 |
float xppinch = 0;
|
|
|
1443 |
float yppinch = 0;
|
|
|
1444 |
const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
|
|
|
1445 |
const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
|
|
|
1446 |
const char* output = (char*)(devnames)+(devnames->wOutputOffset);
|
|
|
1447 |
|
|
|
1448 |
HDC hic = CreateIC(driver, device, output, devmode);
|
|
|
1449 |
|
|
|
1450 |
if (hic) {
|
|
|
1451 |
xppinch = (float)GetDeviceCaps(hic, LOGPIXELSX);
|
|
|
1452 |
yppinch = (float)GetDeviceCaps(hic, LOGPIXELSY);
|
|
|
1453 |
wdev->user_media_size[0] = GetDeviceCaps(hic, PHYSICALWIDTH) * 72.0 / xppinch;
|
|
|
1454 |
wdev->user_media_size[1] = GetDeviceCaps(hic, PHYSICALHEIGHT) * 72.0 / yppinch;
|
|
|
1455 |
DeleteDC(hic);
|
|
|
1456 |
}
|
|
|
1457 |
}
|
|
|
1458 |
|
|
|
1459 |
devmode = NULL;
|
|
|
1460 |
devnames = NULL;
|
|
|
1461 |
|
|
|
1462 |
GlobalUnlock(pd.hDevMode);
|
|
|
1463 |
GlobalUnlock(pd.hDevNames);
|
|
|
1464 |
|
|
|
1465 |
if (wdev->win32_hdevmode != NULL) {
|
|
|
1466 |
GlobalFree(wdev->win32_hdevmode);
|
|
|
1467 |
}
|
|
|
1468 |
if (wdev->win32_hdevnames != NULL) {
|
|
|
1469 |
GlobalFree(wdev->win32_hdevnames);
|
|
|
1470 |
}
|
|
|
1471 |
|
|
|
1472 |
wdev->win32_hdevmode = pd.hDevMode;
|
|
|
1473 |
wdev->win32_hdevnames = pd.hDevNames;
|
|
|
1474 |
|
|
|
1475 |
return TRUE;
|
|
|
1476 |
}
|
|
|
1477 |
|
|
|
1478 |
/* Check that we are dealing with an original device. If this
|
|
|
1479 |
* happens to be a copy made by "copydevice", we will have to
|
|
|
1480 |
* copy the original's handles to the associated Win32 params.
|
|
|
1481 |
*/
|
|
|
1482 |
|
|
|
1483 |
private void
|
|
|
1484 |
win_pr2_copy_check(gx_device_win_pr2 * wdev)
|
|
|
1485 |
{
|
|
|
1486 |
HGLOBAL hdevmode = wdev->win32_hdevmode;
|
|
|
1487 |
HGLOBAL hdevnames = wdev->win32_hdevnames;
|
|
|
1488 |
DWORD devmode_len = (hdevmode) ? GlobalSize(hdevmode) : 0;
|
|
|
1489 |
DWORD devnames_len = (hdevnames) ? GlobalSize(hdevnames) : 0;
|
|
|
1490 |
|
|
|
1491 |
if (wdev->original_device == wdev)
|
|
|
1492 |
return;
|
|
|
1493 |
|
|
|
1494 |
wdev->hdcprn = NULL;
|
|
|
1495 |
wdev->win32_hdevmode = NULL;
|
|
|
1496 |
wdev->win32_hdevnames = NULL;
|
|
|
1497 |
|
|
|
1498 |
wdev->original_device = wdev;
|
|
|
1499 |
|
|
|
1500 |
if (devmode_len) {
|
|
|
1501 |
wdev->win32_hdevmode = GlobalAlloc(0, devmode_len);
|
|
|
1502 |
if (wdev->win32_hdevmode) {
|
|
|
1503 |
memcpy(GlobalLock(wdev->win32_hdevmode), GlobalLock(hdevmode), devmode_len);
|
|
|
1504 |
GlobalUnlock(wdev->win32_hdevmode);
|
|
|
1505 |
GlobalUnlock(hdevmode);
|
|
|
1506 |
}
|
|
|
1507 |
}
|
|
|
1508 |
|
|
|
1509 |
if (devnames_len) {
|
|
|
1510 |
wdev->win32_hdevnames = GlobalAlloc(0, devnames_len);
|
|
|
1511 |
if (wdev->win32_hdevnames) {
|
|
|
1512 |
memcpy(GlobalLock(wdev->win32_hdevnames), GlobalLock(hdevnames), devnames_len);
|
|
|
1513 |
GlobalUnlock(wdev->win32_hdevnames);
|
|
|
1514 |
GlobalUnlock(hdevnames);
|
|
|
1515 |
}
|
|
|
1516 |
}
|
|
|
1517 |
}
|
|
|
1518 |
|
|
|
1519 |
|
|
|
1520 |
/* Modeless dialog box - Cancel printing */
|
|
|
1521 |
BOOL CALLBACK
|
|
|
1522 |
CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
1523 |
{
|
|
|
1524 |
switch (message) {
|
|
|
1525 |
case WM_INITDIALOG:
|
|
|
1526 |
SetWindowText(hDlg, szAppName);
|
|
|
1527 |
return TRUE;
|
|
|
1528 |
case WM_COMMAND:
|
|
|
1529 |
switch (LOWORD(wParam)) {
|
|
|
1530 |
case IDCANCEL:
|
|
|
1531 |
DestroyWindow(hDlg);
|
|
|
1532 |
EndDialog(hDlg, 0);
|
|
|
1533 |
return TRUE;
|
|
|
1534 |
}
|
|
|
1535 |
}
|
|
|
1536 |
return FALSE;
|
|
|
1537 |
}
|
|
|
1538 |
|
|
|
1539 |
|
|
|
1540 |
BOOL CALLBACK
|
|
|
1541 |
AbortProc2(HDC hdcPrn, int code)
|
|
|
1542 |
{
|
|
|
1543 |
process_interrupts(NULL);
|
|
|
1544 |
if (code == SP_OUTOFDISK)
|
|
|
1545 |
return (FALSE); /* cancel job */
|
|
|
1546 |
return (TRUE);
|
|
|
1547 |
}
|
|
|
1548 |
|